Commit 4b08f0e1 authored by Côme Chilliet's avatar Côme Chilliet
Browse files

feat(management) Added ACL check on Action column display

parent 3bcd7058
......@@ -427,7 +427,7 @@ class userinfo
*
* \param string $object The acl category (e.g. user)
*
* \param string $attribute The acl class (e.g. user)
* \param string $attribute
*
* \param bool $skip_write Remove the write acl for this dn
*
......
......@@ -97,7 +97,8 @@ class management
}
$createMenu[] = new Action(
'new_'.$type, $infos['name'], $icon,
'0', 'newEntry'
'0', 'newEntry',
array('c')
);
}
$this->registerAction(
......@@ -116,16 +117,17 @@ class management
$this->registerAction(
new Action(
'remove', _('Remove'), 'geticon.php?context=actions&icon=edit-delete&size=16',
'+', 'removeRequested'
'+', 'removeRequested',
array('d')
)
);
/* Actions from footer are not in any menus and do not need a label */
$this->registerAction(new Action('apply', '', '', '0', 'applyChanges', FALSE));
$this->registerAction(new Action('save', '', '', '0', 'saveChanges', FALSE));
$this->registerAction(new Action('cancel', '', '', '0', 'cancelEdit', FALSE));
$this->registerAction(new Action('cancelDelete', '', '', '0', 'cancelEdit', FALSE));
$this->registerAction(new Action('removeConfirmed', '', '', '0', 'removeConfirmed', FALSE));
$this->registerAction(new HiddenAction('apply', 'applyChanges'));
$this->registerAction(new HiddenAction('save', 'saveChanges'));
$this->registerAction(new HiddenAction('cancel', 'cancelEdit'));
$this->registerAction(new HiddenAction('cancelDelete', 'cancelEdit'));
$this->registerAction(new HiddenAction('removeConfirmed', 'removeConfirmed'));
//~ $this->configureHeadpage();
//~ $this->configureFilter();
......@@ -177,7 +179,7 @@ class management
/*!
* \brief Calls the registered method for a given action/event.
*/
function handleActions(array $action)
function handleAction(array $action)
{
// Start action
if (isset($this->actions[$action['action']])) {
......@@ -213,9 +215,12 @@ class management
//~ session::set('LOCK_VARS_TO_USE', $vars);
// Handle actions (POSTs and GETs)
$str = $this->handleActions($this->detectPostActions());
if ($str) {
return $this->getHeader().$str;
$action = $this->detectPostActions();
if (!empty($action)) {
$str = $this->handleAction($action);
if ($str) {
return $this->getHeader().$str;
}
}
// Open single dialog objects
......@@ -322,8 +327,7 @@ class management
function renderActionColumn($pid, $row, $dn, $type, array $entry)
{
// Go thru all actions
$result = '';
$emptyimg = '<img src="images/empty.png" alt=" " class="center optional"/>';
$result = '';
foreach ($this->actions as $action) {
$result .= $action->renderColumnIcons($pid, $row, $dn, $type, $entry);
}
......
......@@ -30,6 +30,8 @@ class Action
/* 0, 1, + or * */
protected $targets;
protected $acl;
/* Booleans */
protected $inmenu;
protected $inline;
......@@ -39,7 +41,7 @@ class Action
protected $minTargets;
protected $maxTargets;
function __construct($name, $label, $icon, $targets, $callable, $inmenu = TRUE, $inline = TRUE)
function __construct($name, $label, $icon, $targets, $callable, array $acl = array(), $inmenu = TRUE, $inline = TRUE)
{
if ($targets == '0') {
$inline = FALSE;
......@@ -52,6 +54,7 @@ class Action
$this->callable = $callable;
$this->inmenu = $inmenu;
$this->inline = $inline;
$this->acl = $acl;
switch ($targets) {
case '0':
......@@ -123,11 +126,10 @@ class Action
function renderColumnIcons($pid, $row, $dn, $type, array $entry)
{
// TODO Skip the entry completely if there's no permission to execute it
//~ if (!$this->hasActionPermission($action, $dn, $row)) {
//~ $result .= $emptyimg;
//~ continue;
//~ }
// Skip the entry completely if there's no permission to execute it
if (!$this->hasPermission($dn, $type)) {
return '<img src="images/empty.png" alt=" " class="center optional"/>';
}
// TODO? Skip entry if the pseudo filter does not fit
// TODO? Skip depending on type
......@@ -136,6 +138,34 @@ class Action
return '<input class="center" type="image" src="'.htmlentities($this->icon, ENT_COMPAT, 'UTF-8').'"'.
' title="'.$this->label.'" alt="'.$this->label.'" name="listing_'.$this->name.'_'.$row.'"/>';
}
function hasPermission($dn, $type)
{
global $ui;
$infos = objects::infos($type);
foreach ($this->acl as $acl) {
if (preg_match('/([a-zA-Z0-9]+):([rwcdm]+)/', $acl, $m)) {
/* attribute:rw */
$module = $ui->getAttributeCategory($type, $m[1]);
$checkAcl = $ui->get_permissions($dn, $module, $m[1]);
$acl = $m[2];
} else {
$module = $infos['aclCategory'].'/'.$infos['mainTab'];
$checkAcl = $ui->get_permissions($dn, $module, '0');
}
// Split up remaining part of the acl and check rights
$parts = str_split($acl);
foreach ($parts as $part) {
if (strpos($checkAcl, $part) === FALSE) {
return FALSE;
}
}
}
return TRUE;
}
}
/*!
......@@ -147,7 +177,7 @@ class ActionSubMenu extends Action
function __construct($name, $label, $icon, array $actions, $inmenu = TRUE)
{
parent::__construct($name, $label, $icon, '0', FALSE, $inmenu, FALSE);
parent::__construct($name, $label, $icon, '0', FALSE, array(), $inmenu, FALSE);
foreach ($actions as $action) {
$names = $action->listActions();
foreach ($names as $name) {
......@@ -196,3 +226,14 @@ class ActionSubMenu extends Action
{
}
}
/*!
* \brief Action hidden from both column and menu
*/
class HiddenAction extends Action
{
function __construct($name, $callable, array $acl = array())
{
parent::__construct($name, '', '', '0', $callable, $acl, FALSE, FALSE);
}
}
......@@ -1046,126 +1046,6 @@ class managementListing
return $result;
}
function renderActionMenu()
{
// Don't send anything if the menu is not defined
if (!isset($this->xmlData['actionmenu']['action'])) {
return "";
}
// Make sure we got an array of actions
if (isset($this->xmlData['actionmenu']['action']['type'])) {
$this->xmlData['actionmenu']['action'] = array($this->xmlData['actionmenu']['action']);
}
// Load shortcut
$result = '<input type="hidden" name="act" id="actionmenu" value="">'.
'<div style="display:none"><input type="submit" name="exec_act" id="exec_act" value=""/></div>'.
'<ul class="level1" id="root"><li><a href="#">'._('Actions').
'&nbsp;<img class="center optional" src="images/down-arrow.png" alt="down arrow"/></a>';
// Build ul/li list
$result .= $this->recurseActions($this->xmlData['actionmenu']['action']);
return '<div id="pulldown">'.$result.'</li></ul></div>';
}
function renderActionMenuActionLink($separator, $action, $name, $icon)
{
return '<li'.$separator.' id="actionmenu_'.$action.'">'
.'<a href="#" onClick="'
."document.getElementById('actionmenu').value='$action';document.getElementById('exec_act').click();"
.'">'
.'<img src="'.htmlentities($icon, ENT_COMPAT, 'UTF-8').'" alt="'.$action.'" class="center">&nbsp;'.$name.'</a>'
.'</li>';
}
function recurseActions(&$actions)
{
global $class_mapping;
static $level = 2;
$result = "<ul class='level$level'>";
$separator = "";
foreach ($actions as &$action) {
// Skip the entry completely if there's no permission to execute it
if (!$this->hasActionPermission($action, $this->filter->base)) {
continue;
}
// Skip entry if there're missing dependencies
if (isset($action['depends'])) {
$deps = is_array($action['depends']) ? $action['depends'] : array($action['depends']);
foreach ($deps as $clazz) {
if (!isset($class_mapping[$clazz])) {
continue 2;
}
}
}
if ($action['type'] == "separator") {
$separator = " style='border-top:1px solid #AAA' ";
continue;
}
// Dive into subs
if ($action['type'] == "sub" && isset($action['action'])) {
$level++;
if (isset($action['label'])) {
$img = "";
if (isset($action['image'])) {
$img = "<img class='center' src='".htmlentities($action['image'], ENT_COMPAT, 'UTF-8')."' alt='".$action['label']."'/>&nbsp;";
}
$result .= "<li id='actionmenu_".strtolower($action['label'])."'$separator><a href='#'>$img"._($action['label'])."&nbsp;<img src='images/forward-arrow.png' alt='forward arrow'/></a>";
}
// Ensure we've an array of actions, this enables sub menus with only one action.
if (isset($action['action']['type'])) {
$action['action'] = array($action['action']);
}
$result .= $this->recurseActions($action['action'])."</li>";
$level--;
$separator = "";
continue;
}
// Render entry elseways
if (isset($action['label'])) {
$result .= $this->renderActionMenuActionLink($separator, $action['name'], _($action['label']), $action['image']);
}
// Check for special types
switch ($action['type']) {
case 'copypaste':
$cut = !isset($action['cut']) || $action['cut'] != "false";
$copy = !isset($action['copy']) || $action['copy'] != "false";
$result .= $this->renderCopyPasteMenu($separator, $copy, $cut);
break;
case 'snapshot':
$result .= $this->renderSnapshotMenu($separator);
break;
case 'exporter':
$result .= $this->renderExporterMenu($separator);
break;
case 'daemon':
$result .= $this->renderDaemonMenu($separator);
break;
}
$separator = "";
}
unset($action);
$result .= "</ul>";
return $result;
}
/*!
* \brief Check if user have action permission
*
......@@ -1513,14 +1393,6 @@ class managementListing
return NULL;
}
/*!
* \brief Get listing entries
*/
function getEntries()
{
return $this->entries;
}
/*!
* \brief Get type
*
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment