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

feat(management) Clean and fix ACL handling for action menu

parent 140a0b2e
......@@ -44,7 +44,9 @@ class Action
protected $separator = FALSE;
function __construct($name, $label, $icon, $targets, $callable, array $acl = array(), $inmenu = TRUE, $inline = TRUE)
protected $parent;
function __construct($name, $label, $icon, $targets, $callable, array $acls = array(), $inmenu = TRUE, $inline = TRUE)
{
if ($targets == '0') {
$inline = FALSE;
......@@ -57,7 +59,33 @@ class Action
$this->callable = $callable;
$this->inmenu = $inmenu;
$this->inline = $inline;
$this->acl = $acl;
$this->acl = array();
/*
* acl may be of the form:
* acl (ex: 'd')
* attribute:acl (ex: 'userPassword:r')
* category/class/acl (ex: 'user/template/r')
* category/class/attribute:acl (ex: 'user/user/userPassword:r')
* /class/acl (ex: '/snapshot/c')
* /class/attribute:acl (ex: '/template/template_cn:w')
* */
foreach ($acls as $acl) {
$category = NULL;
$class = NULL;
$attribute = '0';
if (strpos($acl, '/') !== FALSE) {
list($category, $class, $acl) = explode('/', $acl, 3);
}
if (strpos($acl, ':') !== FALSE) {
list($attribute, $acl) = explode(':', $acl, 2);
}
$this->acl[] = array(
'category' => $category,
'class' => $class,
'attribute' => $attribute,
'acl' => str_split($acl),
);
}
switch ($targets) {
case '0':
......@@ -85,6 +113,11 @@ class Action
}
}
function setParent(management $parent)
{
$this->parent = $parent;
}
function getName()
{
return $this->name;
......@@ -134,6 +167,10 @@ class Action
return;
}
if (!$this->hasPermission($this->parent->listing->getBase())) {
return;
}
$actions[] = array(
'name' => $this->name,
'icon' => $this->icon,
......@@ -176,29 +213,46 @@ class Action
return TRUE;
}
function hasPermission($dn, $type, $template)
function hasPermission($dn, $type = NULL, $template = FALSE)
{
global $ui;
$infos = objects::infos($type);
if ($type === NULL) {
$types = $this->parent->objectTypes;
} else {
$types = array($type);
}
/*
* if category is missing it’s deducted from type (all types are tested for menu actions)
* if class is missing it’s deducted from attribute if present, otherwise it’s type mainTab
* if attribute is missing 0 is used
*/
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];
$checkAcl = '';
if (!empty($acl['category'])) {
$checkAcl = $ui->get_permissions($dn, $acl['category'].'/'.$acl['class'], $acl['attribute']);
} elseif (empty($acl['class']) && ($acl['attribute'] != '0')) {
foreach ($types as $type) {
$module = $ui->getAttributeCategory($type, $acl['attribute']);
$checkAcl .= $ui->get_permissions($dn, $module, $acl['attribute']);
}
} else {
if ($template) {
$module = $infos['aclCategory'].'/template';
} else {
$module = $infos['aclCategory'].'/'.$infos['mainTab'];
foreach ($types as $type) {
$infos = objects::infos($type);
if (!empty($acl['class'])) {
/* Class with empty category may be used in special cases like '/snapshot/c'*/
$module = $infos['aclCategory'].'/'.$acl['class'];
} elseif ($template) {
$module = $infos['aclCategory'].'/template';
} else {
$module = $infos['aclCategory'].'/'.$infos['mainTab'];
}
$checkAcl .= $ui->get_permissions($dn, $module, $acl['attribute']);
}
$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) {
// Check rights
foreach ($acl['acl'] as $part) {
if (strpos($checkAcl, $part) === FALSE) {
return FALSE;
}
......
......@@ -38,6 +38,15 @@ class SubMenuAction extends Action
}
}
function setParent(management $parent)
{
parent::setParent($parent);
foreach ($this->actions as $action) {
$action->setParent($parent);
}
}
function listActions()
{
return array_keys($this->handlers);
......@@ -57,17 +66,21 @@ class SubMenuAction extends Action
if (!$this->inmenu) {
return;
}
$subactions = array();
foreach ($this->actions as $action) {
$action->fillMenuItems($subactions);
}
$actions[] = array(
'name' => $this->name,
'icon' => $this->icon,
'label' => $this->label,
'separator' => $this->separator,
'actions' => $subactions
);
if (!empty($subactions)) {
$actions[] = array(
'name' => $this->name,
'icon' => $this->icon,
'label' => $this->label,
'separator' => $this->separator,
'actions' => $subactions
);
}
}
function renderColumnIcons(ListingEntry $entry)
......
......@@ -144,19 +144,18 @@ class management
$createMenu[] = new Action(
'new_'.$type, $infos['name'], $icon,
'0', 'newEntry',
array('c')
array($infos['aclCategory'].'/'.$infos['mainTab'].'/c')
);
if (!static::$skipTemplates) {
// TODO fix ACL
$templateMenu[] = new Action(
'new_template_'.$type, $infos['name'], $icon,
'0', 'newEntryTemplate',
array('c')
array($infos['aclCategory'].'/template/c')
);
$fromTemplateMenu[] = new Action(
'template_apply_'.$type, $infos['name'], $icon,
'?', 'newEntryFromTemplate',
array('c')
array($infos['aclCategory'].'/template/r', $infos['aclCategory'].'/'.$infos['mainTab'].'/c')
);
}
}
......@@ -245,14 +244,15 @@ class management
$this->registerAction(
new Action(
'snapshot', _('Create snapshot'), 'geticon.php?context=actions&icon=snapshot&size=16',
'1', 'createSnapshotDialog'
'1', 'createSnapshotDialog',
array('/snapshot/c')
)
);
$this->registerAction(
new Action(
'restore', _('Restore snapshot'), 'geticon.php?context=actions&icon=document-restore&size=16',
'*', 'restoreSnapshotDialog',
array('w')
array('w', '/snapshot/r')
)
);
$this->actions['snapshot']->setSeparator(TRUE);
......@@ -273,6 +273,7 @@ class management
*/
function registerAction(Action $action)
{
$action->setParent($this);
$this->actions[$action->getName()] = $action;
foreach ($action->listActions() as $actionName) {
$this->actionHandlers[$actionName] = $action;
......
......@@ -51,6 +51,10 @@ class LockAction extends Action
return;
}
if (!$this->hasPermission($this->parent->listing->getBase())) {
return;
}
$actions[] = array(
'name' => $this->name.'_lock',
'icon' => $this->icon['lock'],
......
Markdown is supported
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