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

:sparkles: feat(dashboard): Add ACL handling in dashboard

Now there is an ACL you can put in any ACL role to give access to the
 dashboard.
And all searches from the dashboard are checking ACL and returning info
 only on the data you are allowed to see.
Plugins providing a dashboard tab will have to be adapted as well

issue #5734
Showing with 104 additions and 49 deletions
+104 -49
......@@ -84,6 +84,9 @@ class objects
if ($category === FALSE) {
throw new FusionDirectoryException('Could not find ACL for attribute "'.$search_attr.'"');
}
if ($category === TRUE) {
continue;
}
if (strpos($ui->get_permissions($ou, $category, $search_attr), 'r') === FALSE) {
$attrsAcls[$search_attr] = array($category, $search_attr);
}
......@@ -97,15 +100,22 @@ class objects
}
try {
$ldap = static::search($types, $search_attrs, $ou, $filter, $checkAcl, $scope);
$ldap = static::search($types, $search_attrs, $ou, $filter, $checkAcl, $scope, FALSE, $partialFilterAcls);
} catch (NonExistingBranchException $e) {
return array();
}
$result = array();
while ($fetched_attrs = $ldap->fetch()) {
$key = $fetched_attrs['dn'];
if ($checkAcl && !preg_match('/r/', $ui->get_permissions($key, $acl))) {
continue;
if ($checkAcl) {
if (strpos($ui->get_permissions($key, $acl), 'r') === FALSE) {
continue;
}
foreach ($partialFilterAcls as $partialFilterAcl) {
if (strpos($ui->get_permissions($key, $partialFilterAcl[0], $partialFilterAcl[1]), 'r') === FALSE) {
continue;
}
}
}
if (is_array($attrs)) {
$result[$key] = array();
......@@ -153,7 +163,10 @@ class objects
static function count ($types, $ou = NULL, $filter = '', $checkAcl = FALSE)
{
try {
$ldap = static::search($types, array('dn'), $ou, $filter, $checkAcl);
$ldap = static::search($types, array('dn'), $ou, $filter, $checkAcl, 'subtree', FALSE, $partialFilterAcls);
if (!empty($partialFilterAcls)) {
throw new FusionDirectoryException('Not enough rights to use "'.$partialFilterAcls[0][1].'" in filter');
}
} catch (EmptyFilterException $e) {
return 0;
} catch (NonExistingBranchException $e) {
......@@ -162,10 +175,12 @@ class objects
return $ldap->count();
}
private static function search ($types, $search_attrs, $ou = NULL, $filter = '', $checkAcl = FALSE, $scope = 'subtree', $templateSearch = FALSE)
private static function search ($types, $search_attrs, $ou = NULL, $filter = '', $checkAcl = FALSE, $scope = 'subtree', $templateSearch = FALSE, &$partialFilterAcls = array())
{
global $config, $ui;
$partialFilterAcls = array();
if (!is_array($types)) {
$types = array($types);
}
......@@ -212,8 +227,11 @@ class objects
if ($category === FALSE) {
throw new FusionDirectoryException('Could not find ACL for attribute "'.$acl.'"');
}
if ($category === TRUE) {
continue;
}
if (strpos($ui->get_permissions($ou, $category, $acl), 'r') === FALSE) {
throw new FusionDirectoryException('Not enough rights to use "'.$acl.'" in filter');
$partialFilterAcls[] = array($category, $acl);
}
}
}
......
......@@ -987,13 +987,16 @@ class userinfo
/* \brief Search which ACL category should be used for this attribute and this object type, if any
*
* \return The ACL catogory or FALSE if not found
* \return The ACL category, or FALSE if not found, or TRUE if acl check should be bypassed
*/
function getAttributeCategory($type, $attribute)
{
global $config;
$infos = objects::infos($type);
$classes = $config->data['CATEGORIES'][$infos['aclCategory']]['classes'];
if (in_array_ics($attribute, array('objectClass', 'dn'))) {
return TRUE;
}
foreach ($classes as $class) {
if ($class == '0') {
continue;
......
......@@ -38,7 +38,9 @@ class dashboard extends simplePlugin
'plSection' => array('reporting' => array('name' => _('Reporting'), 'priority' => 30)),
'plPriority' => 0,
'plProvidedAcls' => array()
'plProvidedAcls' => array(
'dashboard' => _('See dashboard')
)
);
}
......@@ -67,7 +69,9 @@ class dashboard extends simplePlugin
$stats = array();
foreach ($config->data['OBJECTS'] as $type => $infos) {
try {
$nb = objects::count($type);
$nb = count(objects::ls($type, NULL, NULL, '', TRUE));
} catch (EmptyFilterException $e) {
$nb = 0;
} catch (FusionDirectoryException $e) {
$nb = 0;
msg_dialog::display(
......
......@@ -57,7 +57,7 @@ class dashboardPassword extends simplePlugin
$defaultMethod = $config->get_cfg_value('passwordDefaultHash', 'ssha');
$forceDefault = ($config->get_cfg_value('forcePasswordDefaultHash', 'FALSE') == 'TRUE');
try {
$users = objects::ls('user', 'userPassword');
$users = objects::ls('user', 'userPassword', NULL, '', TRUE);
} catch (LDAPFailureException $e) {
msg_dialog::display(
_('LDAP error'),
......
......@@ -81,25 +81,22 @@ class dashboardUsers extends simplePlugin
global $config;
/* User statistics */
try {
$nb_accounts = objects::count('user');
$nb_accounts = count(objects::ls('user', NULL, NULL, '', TRUE));
$nb_mail_accounts = count(objects::ls('user', NULL, NULL, '(objectClass=gosaMailAccount)', TRUE));
$nb_posix_accounts = count(objects::ls('user', NULL, NULL, '(objectClass=posixAccount)', TRUE));
$nb_samba_accounts = count(objects::ls('user', NULL, NULL, '(objectClass=sambaSamAccount)', TRUE));
} catch (LDAPFailureException $e) {
msg_dialog::display(
_('LDAP error'),
sprintf(_('Total user number could not be computed because of the following LDAP error: %s'), $e->getMessage()),
sprintf(_('User statistics could not be computed because of the following LDAP error: %s'), $e->getMessage()),
ERROR_DIALOG
);
$nb_accounts = 0;
$nb_accounts = 0;
$nb_mail_accounts = 0;
$nb_posix_accounts = 0;
$nb_samba_accounts = 0;
}
$ldap = $config->get_ldap_link();
$ldap->cd($config->current['BASE']);
$ldap->search('(&(objectClass=inetOrgPerson)(objectClass=gosaMailAccount))', array('cn'));
$nb_mail_accounts = $ldap->count();
$ldap->search('(&(objectClass=inetOrgPerson)(objectClass=posixAccount))', array('cn'));
$nb_posix_accounts = $ldap->count();
$ldap->search('(&(objectClass=inetOrgPerson)(objectClass=sambaSamAccount))', array('cn'));
$nb_samba_accounts = $ldap->count();
return array(
'accounts' => array(
array('name' => 'mail', 'nb' => $nb_mail_accounts, 'img' => 'geticon.php?context=applications&icon=internet-mail&size=16'),
......@@ -115,21 +112,27 @@ class dashboardUsers extends simplePlugin
{
global $config;
/* Group statistics */
$ldap = $config->get_ldap_link();
$ldap->cd($config->current['BASE']);
$ldap->search('(objectClass=posixGroup)', array('cn'));
$nb = $ldap->count();
$ldap->search('(&(objectClass=posixGroup)(objectClass=fdGroupMail))', array('cn'));
$nb_mail_groups = $ldap->count();
$ldap->search('(&(objectClass=posixGroup)(objectClass=sambaSamAccount))', array('cn'));
$nb_samba_groups = $ldap->count();
try {
$nb_groups = count(objects::ls('group', NULL, NULL, '', TRUE));
$nb_mail_groups = count(objects::ls('group', NULL, NULL, '(objectClass=fdGroupMail)', TRUE));
$nb_samba_groups = count(objects::ls('group', NULL, NULL, '(objectClass=sambaSamAccount)', TRUE));
} catch (LDAPFailureException $e) {
msg_dialog::display(
_('LDAP error'),
sprintf(_('Group statistics could not be computed because of the following LDAP error: %s'), $e->getMessage()),
ERROR_DIALOG
);
$nb_groups = 0;
$nb_mail_groups = 0;
$nb_samba_accounts = 0;
}
return array(
'groups' => array(
array('name' => 'mail', 'nb' => $nb_mail_groups, 'img' => 'geticon.php?context=applications&icon=internet-mail&size=16'),
array('name' => 'samba', 'nb' => $nb_samba_groups, 'img' => 'geticon.php?context=applications&icon=os-windows&size=16')
),
'nb' => $nb,
'nb' => $nb_groups,
'img' => 'geticon.php?context=types&icon=user-group&size=16',
);
}
......@@ -143,33 +146,52 @@ class dashboardUsers extends simplePlugin
/* getting the date in TIMESTAMP UNIX format */
/* 24 * 60 * 60 = 86400 */
$today = floor(time() / 86400);
$today = floor(time() / 86400);
/* Fetch global value from fusiondirectory.conf */
$next_expired_days = $config->get_cfg_value('dashboardExpiredAccountsDays', 15);
$next_expired_date = ($today + $next_expired_days);
/* search all account with all date, mail, telephone */
$ldap = $config->get_ldap_link();
$ldap->cd($config->current['BASE']);
$ldap->search(
'(shadowExpire=*)',
array('uid','shadowExpire','mail','telephoneNumber','cn','manager')
);
try {
$users = objects::ls('user', array(
'dn' => 'raw',
'uid' => 'raw',
'cn' => 'raw',
'mail' => 'raw',
'telephoneNumber' => 'raw',
'manager' => 'raw',
'shadowExpire' => 1,
), NULL, '(shadowExpire=*)', TRUE);
} catch (LDAPFailureException $e) {
msg_dialog::display(
_('LDAP error'),
sprintf(_('Expired user information could not be computed because of the following LDAP error: %s'), $e->getMessage()),
ERROR_DIALOG
);
$users = array();
} catch (FusionDirectoryException $e) {
msg_dialog::display(
_('Error'),
sprintf(_('Expired user information could not be computed because of the following error: %s'), $e->getMessage()),
ERROR_DIALOG
);
$users = array();
}
$expired_accounts = array();
$next_expired_accounts = array();
while ($attrs = $ldap->fetch()) {
$expired_accounts = array();
$next_expired_accounts = array();
foreach ($users as $user) {
// Test if account is expired now
if ($attrs['shadowExpire'][0] <= $today) {
$expired_accounts[] = static::get_user_infos($attrs);
} elseif ($attrs['shadowExpire'][0] <= $next_expired_date) {
$next_expired_accounts[] = static::get_user_infos($attrs);
if ($user['shadowExpire'] <= $today) {
$expired_accounts[] = static::get_user_infos($user);
} elseif ($user['shadowExpire'] <= $next_expired_date) {
$next_expired_accounts[] = static::get_user_infos($user);
}
}
uasort($expired_accounts, array('dashboardUsers','compareUsers'));
uasort($next_expired_accounts, array('dashboardUsers','compareUsers'));
uasort($expired_accounts, array('dashboardUsers','compareUsers'));
uasort($next_expired_accounts, array('dashboardUsers','compareUsers'));
return array(
'columns' => $this->expiredAccountsColumns,
......
......@@ -4,7 +4,11 @@
</span>
<div>
<img src="{$attributes.groups_stats.img|escape}" alt="group icon"/>
{t count=$attributes.groups_stats.nb 1=$attributes.groups_stats.nb plural="There are %1 groups:"}There is 1 group:{/t}
{if $attributes.groups_stats.nb > 0}
{t count=$attributes.groups_stats.nb 1=$attributes.groups_stats.nb plural="There are %1 groups:"}There is 1 group:{/t}
{else}
{t}There are no groups{/t}
{/if}
<ul>
{foreach from=$attributes.groups_stats.groups item=g}
<li style="list-style-image:url({$g.img|escape})">
......
......@@ -4,7 +4,11 @@
</span>
<div>
<img src="{$attributes.users_stats.img|escape}" alt="user icon"/>
{t count=$attributes.users_stats.nb 1=$attributes.users_stats.nb plural="There are %1 users:"}There is 1 user:{/t}
{if $attributes.users_stats.nb > 0}
{t count=$attributes.users_stats.nb 1=$attributes.users_stats.nb plural="There are %1 users:"}There is 1 user:{/t}
{else}
{t}There are no users{/t}
{/if}
<ul>
{foreach from=$attributes.users_stats.accounts item=acc}
<li style="list-style-image:url({$acc.img|escape})">
......
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