mirror of
https://github.com/e107inc/e107.git
synced 2025-08-05 06:07:32 +02:00
Admin menu 'userclass' option added;
Improved, simplified and detailed admin UI access control Default admin controller 403 page added
This commit is contained in:
@@ -422,7 +422,8 @@ if ($e107_popup != 1)
|
|||||||
* $e107_vars['action']['text'] -> link title
|
* $e107_vars['action']['text'] -> link title
|
||||||
* $e107_vars['action']['link'] -> if empty '#action' will be added as href attribute
|
* $e107_vars['action']['link'] -> if empty '#action' will be added as href attribute
|
||||||
* $e107_vars['action']['image'] -> (new) image tag
|
* $e107_vars['action']['image'] -> (new) image tag
|
||||||
* $e107_vars['action']['perm'] -> permissions
|
* $e107_vars['action']['perm'] -> permissions via getperms()
|
||||||
|
* $e107_vars['action']['userclass'] -> user class permissions via check_class()
|
||||||
* $e107_vars['action']['include'] -> additional <a> tag attributes
|
* $e107_vars['action']['include'] -> additional <a> tag attributes
|
||||||
* $e107_vars['action']['sub'] -> (new) array, exactly the same as $e107_vars' first level e.g. $e107_vars['action']['sub']['action2']['link']...
|
* $e107_vars['action']['sub'] -> (new) array, exactly the same as $e107_vars' first level e.g. $e107_vars['action']['sub']['action2']['link']...
|
||||||
* $e107_vars['action']['sort'] -> (new) used only if found in 'sub' array - passed as last parameter (recursive call)
|
* $e107_vars['action']['sort'] -> (new) used only if found in 'sub' array - passed as last parameter (recursive call)
|
||||||
@@ -502,7 +503,13 @@ if ($e107_popup != 1)
|
|||||||
$search[9] = '/\{LINK_IMAGE\}(.*?)/si';
|
$search[9] = '/\{LINK_IMAGE\}(.*?)/si';
|
||||||
foreach (array_keys($e107_vars) as $act)
|
foreach (array_keys($e107_vars) as $act)
|
||||||
{
|
{
|
||||||
if (vartrue($e107_vars[$act]['perm']) && !getperms($e107_vars[$act]['perm'])) // check perms first.
|
if (isset($e107_vars[$act]['perm']) && !getperms($e107_vars[$act]['perm'])) // check perms first.
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check class so that e.g. e_UC_NOBODY will result no permissions granted (even for main admin)
|
||||||
|
if (isset($e107_vars[$act]['userclass']) && !e107::getUser()->checkClass($e107_vars[$act]['userclass'], false)) // check userclass perms
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@@ -942,7 +942,25 @@ class e_admin_dispatcher
|
|||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $modes;
|
protected $modes = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional - access restrictions per action
|
||||||
|
* Access array in format (similar to adminMenu)
|
||||||
|
* 'MODE/ACTION' => e_UC_* (userclass constant, or custom userclass ID if dynamically set)
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $access = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional - generic entry point access restriction (via getperms())
|
||||||
|
* Value of this for plugins would be always 'P'.
|
||||||
|
* More detailed access control is granted with $access and $modes[MODE]['perm'] or $modes[MODE]['userclass'] settings
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $perm;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
@@ -964,6 +982,8 @@ class e_admin_dispatcher
|
|||||||
* Optional (set by child class).
|
* Optional (set by child class).
|
||||||
* Required for admin menu render
|
* Required for admin menu render
|
||||||
* Format: 'mode/action' => array('caption' => 'Link title'[, 'perm' => '0', 'url' => '{e_PLUGIN}plugname/admin_config.php'], ...);
|
* Format: 'mode/action' => array('caption' => 'Link title'[, 'perm' => '0', 'url' => '{e_PLUGIN}plugname/admin_config.php'], ...);
|
||||||
|
* Note that 'perm' and 'userclass' restrictions are inherited from the $modes, $access and $perm, so you don't have to set that vars if
|
||||||
|
* you don't need any additional 'visual' control.
|
||||||
* All valid key-value pair (see e_admin_menu function) are accepted.
|
* All valid key-value pair (see e_admin_menu function) are accepted.
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
@@ -1010,11 +1030,13 @@ class e_admin_dispatcher
|
|||||||
// register itself
|
// register itself
|
||||||
e107::setRegistry('admin/ui/dispatcher', $this);
|
e107::setRegistry('admin/ui/dispatcher', $this);
|
||||||
|
|
||||||
|
// permissions and restrictions
|
||||||
|
$this->checkAccess();
|
||||||
|
|
||||||
if($auto_observe)
|
if($auto_observe)
|
||||||
{
|
{
|
||||||
$this->runObservers(true);
|
$this->runObservers(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1025,6 +1047,63 @@ class e_admin_dispatcher
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function checkAccess()
|
||||||
|
{
|
||||||
|
$request = $this->getRequest();
|
||||||
|
$currentMode = $request->getMode();
|
||||||
|
|
||||||
|
// access based on mode setting - general controller access
|
||||||
|
if(!$this->checkModeAccess($currentMode))
|
||||||
|
{
|
||||||
|
$request->setAction('e403');
|
||||||
|
e107::getMessage()->addError('You don\'t have permissions to view this page.')
|
||||||
|
->addDebug('Mode access restriction triggered.');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// access based on $access settings - access per action
|
||||||
|
$currentAction = $request->getAction();
|
||||||
|
$route = $currentMode.'/'.$currentAction;
|
||||||
|
if(!$this->checkRouteAccess($route))
|
||||||
|
{
|
||||||
|
$request->setAction('e403');
|
||||||
|
e107::getMessage()->addError('You don\'t have permissions to view this page.')
|
||||||
|
->addDebug('Route access restriction triggered.');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function checkModeAccess($mode)
|
||||||
|
{
|
||||||
|
// mode userclass (former check_class())
|
||||||
|
if(isset($this->modes[$mode]['userclass']) && !e107::getUser()->checkClass($this->modes[$mode]['userclass'], false))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// mode admin permission (former getperms())
|
||||||
|
if(isset($this->modes[$mode]['perm']) && !e107::getUser()->checkAdminPerms($this->modes[$mode]['perm']))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// generic dispatcher admin permission (former getperms())
|
||||||
|
if(null !== $this->perm && !e107::getUser()->checkAdminPerms($this->perm))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function checkRouteAccess($route)
|
||||||
|
{
|
||||||
|
if(isset($this->access[$route]) && !e107::getUser()->checkClass($this->access[$route], false))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve missing default action/mode
|
* Retrieve missing default action/mode
|
||||||
* @return e_admin_dispatcher
|
* @return e_admin_dispatcher
|
||||||
@@ -1093,12 +1172,13 @@ class e_admin_dispatcher
|
|||||||
/**
|
/**
|
||||||
* Dispatch & render all
|
* Dispatch & render all
|
||||||
*
|
*
|
||||||
* @param boolean $return if true, array(title, body, render_mod) will be returned
|
* @param boolean $run_header see runObservers()
|
||||||
|
* @param boolean $return see runPage()
|
||||||
* @return string|array current admin page body
|
* @return string|array current admin page body
|
||||||
*/
|
*/
|
||||||
public function run($return = false)
|
public function run($run_header = true, $return = 'render')
|
||||||
{
|
{
|
||||||
return $this->runObserver()->renderPage($return);
|
return $this->runObservers()->runPage($return);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1275,7 +1355,6 @@ class e_admin_dispatcher
|
|||||||
// Not known controller (not found in e_admin_dispatcher::$modes) exception
|
// Not known controller (not found in e_admin_dispatcher::$modes) exception
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var_dump($this->getDefaultControllerName(), $this->modes);
|
|
||||||
// TODO - admin log
|
// TODO - admin log
|
||||||
$this->_current_controller = $this->getDefaultController();
|
$this->_current_controller = $this->getDefaultController();
|
||||||
// add messages
|
// add messages
|
||||||
@@ -1321,6 +1400,12 @@ class e_admin_dispatcher
|
|||||||
{
|
{
|
||||||
$tmp = explode('/', trim($key, '/'), 3);
|
$tmp = explode('/', trim($key, '/'), 3);
|
||||||
|
|
||||||
|
// sync with mode/route access
|
||||||
|
if(!$this->checkModeAccess($tmp[0]) || !$this->checkRouteAccess($tmp[0].'/'.$tmp[1]))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// custom 'selected' check
|
// custom 'selected' check
|
||||||
if(isset($val['selected']) && $val['selected']) $selected = $val['selected'] === true ? $key : $val['selected'];
|
if(isset($val['selected']) && $val['selected']) $selected = $val['selected'] === true ? $key : $val['selected'];
|
||||||
|
|
||||||
@@ -1348,14 +1433,15 @@ class e_admin_dispatcher
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($val['perm']!= null) // check perms
|
// Access check done above
|
||||||
{
|
// if($val['perm']!= null) // check perms
|
||||||
if(getperms($val['perm']))
|
// {
|
||||||
{
|
// if(getperms($val['perm']))
|
||||||
$var[$key][$k2] = $v;
|
// {
|
||||||
}
|
// $var[$key][$k2] = $v;
|
||||||
}
|
// }
|
||||||
else
|
// }
|
||||||
|
// else
|
||||||
{
|
{
|
||||||
$var[$key][$k2] = $v;
|
$var[$key][$k2] = $v;
|
||||||
}
|
}
|
||||||
@@ -1372,6 +1458,8 @@ class e_admin_dispatcher
|
|||||||
$var[$key]['perm'] = $val['perm']; */
|
$var[$key]['perm'] = $val['perm']; */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(empty($var)) return '';
|
||||||
|
|
||||||
$request = $this->getRequest();
|
$request = $this->getRequest();
|
||||||
if(!$selected) $selected = $request->getMode().'/'.$request->getAction();
|
if(!$selected) $selected = $request->getMode().'/'.$request->getAction();
|
||||||
$selected = vartrue($this->adminMenuAliases[$selected], $selected);
|
$selected = vartrue($this->adminMenuAliases[$selected], $selected);
|
||||||
@@ -1401,6 +1489,22 @@ class e_admin_controller
|
|||||||
*/
|
*/
|
||||||
protected $_default_action = 'index';
|
protected $_default_action = 'index';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List (numerical array) of only allowed for this controller actions
|
||||||
|
* Useful to grant access for certain pre-defined actions only
|
||||||
|
* XXX - we may move this in dispatcher (or even having it also there), still searching the most 'friendly' way
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $allow = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List (numerical array) of only disallowed for this controller actions
|
||||||
|
* Useful to restrict access for certain pre-defined actions only
|
||||||
|
* XXX - we may move this in dispatcher (or even having it also there), still searching the most 'friendly' way
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $disallow = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
* @param e_admin_request $request [optional]
|
* @param e_admin_request $request [optional]
|
||||||
@@ -1411,6 +1515,36 @@ class e_admin_controller
|
|||||||
$this->setRequest($request)
|
$this->setRequest($request)
|
||||||
->setResponse($response)
|
->setResponse($response)
|
||||||
->setParams($params);
|
->setParams($params);
|
||||||
|
|
||||||
|
$this->checkAccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check against allowed/disallowed actions
|
||||||
|
*/
|
||||||
|
public function checkAccess()
|
||||||
|
{
|
||||||
|
$request = $this->getRequest();
|
||||||
|
$currentAction = $request->getAction();
|
||||||
|
|
||||||
|
// access based on mode setting - general controller access
|
||||||
|
if(!empty($this->disallow) && in_array($currentAction, $this->disallow))
|
||||||
|
{
|
||||||
|
$request->setAction('e403');
|
||||||
|
e107::getMessage()->addError('You don\'t have permissions to view this page.')
|
||||||
|
->addDebug('Controller action disallowed restriction triggered.');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// access based on $access settings - access per action
|
||||||
|
if(!empty($this->allow) && !in_array($currentAction, $this->allow))
|
||||||
|
{
|
||||||
|
$request->setAction('e403');
|
||||||
|
e107::getMessage()->addError('You don\'t have permissions to view this page.')
|
||||||
|
->addDebug('Controller action not in allowed list restriction triggered.');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1521,6 +1655,15 @@ class e_admin_controller
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current dispatcher object
|
||||||
|
* @return e_admin_dispatcher
|
||||||
|
*/
|
||||||
|
public function getDispatcher()
|
||||||
|
{
|
||||||
|
return e107::getRegistry('admin/ui/dispatcher');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request proxy method
|
* Request proxy method
|
||||||
* @param string $key [optional]
|
* @param string $key [optional]
|
||||||
@@ -1842,6 +1985,23 @@ class e_admin_controller
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function E403Observer()
|
||||||
|
{
|
||||||
|
$this->getResponse()->setTitle(LAN_UI_403_TITLE_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function E403Page()
|
||||||
|
{
|
||||||
|
return '<div class="center">'.LAN_UI_403_BODY_ERROR.'</div>'; // TODO - lan
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function E403AjaxPage()
|
||||||
|
{
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generic redirect handler, it handles almost everything we would need.
|
* Generic redirect handler, it handles almost everything we would need.
|
||||||
* Additionally, it moves currently registered system messages to SESSION message stack
|
* Additionally, it moves currently registered system messages to SESSION message stack
|
||||||
|
@@ -343,6 +343,8 @@ define('LAN_UI_BATCHDEL_ERROR', 'Batch delete not allowed!');
|
|||||||
define('LAN_UI_404_BODY_ERROR', 'Requested page was not found!');
|
define('LAN_UI_404_BODY_ERROR', 'Requested page was not found!');
|
||||||
define('LAN_UI_404_TITLE_ERROR', 'Page Not Found');
|
define('LAN_UI_404_TITLE_ERROR', 'Page Not Found');
|
||||||
define('LAN_UI_404_METHOD_ERROR', 'Action <strong>%1$s</strong> not found!');
|
define('LAN_UI_404_METHOD_ERROR', 'Action <strong>%1$s</strong> not found!');
|
||||||
|
define('LAN_UI_403_BODY_ERROR', 'Access to the requested page is denied.');
|
||||||
|
define('LAN_UI_403_TITLE_ERROR', 'Access denied');
|
||||||
define('LAN_UI_FORM_METHOD_ERROR', 'FATAL ERROR: The field name <strong>%1$s</strong> is not allowed. Please rename the key <strong>%1$s</strong> to something else in your fields array and database table (if required).');
|
define('LAN_UI_FORM_METHOD_ERROR', 'FATAL ERROR: The field name <strong>%1$s</strong> is not allowed. Please rename the key <strong>%1$s</strong> to something else in your fields array and database table (if required).');
|
||||||
|
|
||||||
define('LAN_UI_BATCH_UPDATE_SUCCESS', '<strong>%1$s</strong> set for <strong>%2$d</strong> record(s).');
|
define('LAN_UI_BATCH_UPDATE_SUCCESS', '<strong>%1$s</strong> set for <strong>%2$d</strong> record(s).');
|
||||||
|
Reference in New Issue
Block a user