From f3fb2d1a99259320b0c6d4cdb4b15bf4928925c6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=B4me=20Chilliet?= <come@opensides.be>
Date: Thu, 6 Apr 2017 17:59:42 +0200
Subject: [PATCH] Fixes #5470 Added a blacklist system for plugins menu

---
 contrib/openldap/core-fd-conf.schema  |  7 ++++
 include/class_pluglist.inc            | 31 ++++++++------
 include/class_userinfo.inc            | 18 ++++++++
 plugins/config/class_configInLdap.inc | 60 +++++++++++++++++++++++++++
 4 files changed, 103 insertions(+), 13 deletions(-)

diff --git a/contrib/openldap/core-fd-conf.schema b/contrib/openldap/core-fd-conf.schema
index 4fbed2ffd..b2831c699 100644
--- a/contrib/openldap/core-fd-conf.schema
+++ b/contrib/openldap/core-fd-conf.schema
@@ -367,6 +367,12 @@ attributetype ( 1.3.6.1.4.1.38414.8.18.8 NAME 'fdDefaultShell'
   SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
   SINGLE-VALUE)
 
+attributetype ( 1.3.6.1.4.1.38414.8.18.9 NAME 'fdPluginsMenuBlacklist'
+  DESC 'FusionDirectory - Blacklist as groupdn|plugin or roledn|plugin'
+  EQUALITY caseIgnoreMatch
+  SUBSTR caseIgnoreSubstringsMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
 # Plugins
 
 attributetype ( 1.3.6.1.4.1.38414.8.19.1 NAME 'fdOGroupRDN'
@@ -548,6 +554,7 @@ objectclass ( 1.3.6.1.4.1.38414.8.2.1 NAME 'fusionDirectoryConf'
     fdDisplayErrors $ fdLdapMaxQueryTime $ fdLdapStats $ fdDebugLevel $
     fdEnableSnapshots $ fdSnapshotBase $
     fdTabHook $ fdShells $ fdDefaultShell $ fdDisplayHookOutput $
+    fdPluginsMenuBlacklist $
     fdAclTabOnObjects $ fdDepartmentCategories $
     fdSslCaCertPath $ fdSslKeyPath $ fdSslCertPath $
     fdCasActivated $ fdCasServerCaCertPath $ fdCasHost $ fdCasPort $ fdCasContext
diff --git a/include/class_pluglist.inc b/include/class_pluglist.inc
index ff2e569bc..c8248aa3a 100644
--- a/include/class_pluglist.inc
+++ b/include/class_pluglist.inc
@@ -212,9 +212,20 @@ class pluglist {
    *
    * \return Boolean TRUE on success FALSE otherwise
    */
-  function check_access($aclname)
+  function check_access($infos)
   {
     global $ui;
+
+    if (isset($infos['CLASS']) && $ui->isBlacklisted($infos['CLASS'])) {
+      return FALSE;
+    }
+
+    if (!isset($infos['ACL'])) {
+      return FALSE;
+    }
+
+    $aclname = $infos['ACL'];
+
     if (isset($this->silly_cache[$aclname])) {
       return $this->silly_cache[$aclname];
     }
@@ -320,18 +331,15 @@ class pluglist {
 
         /* Parse sub-plugins */
         foreach ($config->data['MENU'][$section] as $info) {
+          if (!$this->check_access($info)) {
+            continue;
+          }
           if (isset($info['CLASS']) && plugin_available($info['CLASS'])) {
-            if (!$this->check_access($info['ACL'])) {
-              continue;
-            }
             $index  = $this->get_index($info['CLASS']);
             $this->allowed_plugins[$index] = $index;
             list ($plHeadline, $plDescription, $href, ) = $this->get_infos($info['CLASS']);
             $id             = $info['CLASS'];
           } elseif (!isset($info['CLASS'])) {
-            if (isset($info['ACL']) && !$this->check_access($info['ACL'])) {
-              continue;
-            }
             $plHeadline     = $info['TITLE'];
             $plDescription  = $info['DESCRIPTION'];
             $href           = $info['LINK'];
@@ -388,17 +396,14 @@ class pluglist {
         $menu     .= $section_infos['NAME']."</h1>\n";
 
         foreach ($config->data['MENU'][$section] as $info) {
+          if (!$this->check_access($info)) {
+            continue;
+          }
           if (isset($info['CLASS']) && plugin_available($info['CLASS'])) {
-            if (!$this->check_access($info['ACL'])) {
-              continue;
-            }
             /* Read information from class variable */
             list ($plHeadline, $plDescription, $href, $plIcon) = $this->get_infos($info['CLASS']);
             $id             = $info['CLASS'];
           } elseif (!isset($info['CLASS'])) {
-            if (isset($info['ACL']) && !$this->check_access($info['ACL'])) {
-              continue;
-            }
             $plHeadline     = $info['TITLE'];
             $plDescription  = $info['DESCRIPTION'];
             $href           = $info['LINK'];
diff --git a/include/class_userinfo.inc b/include/class_userinfo.inc
index 8b1f53781..2bdae416f 100644
--- a/include/class_userinfo.inc
+++ b/include/class_userinfo.inc
@@ -966,5 +966,23 @@ class userinfo
     }
     return ($this->get_permissions($config->current['BASE'], 'user/user') == 'rwcdm');
   }
+
+  /* \brief Test if a plugin is blacklisted for this user (does not show up in the menu)
+   */
+  function isBlacklisted($plugin)
+  {
+    global $config;
+    $blacklist = $config->get_cfg_value('PluginsMenuBlacklist', array());
+    foreach ($blacklist as $item) {
+      list ($group, $p) = explode('|', $item, 2);
+      if ($plugin == $p) {
+        if (in_array($group, $this->groups) || in_array($group, $this->roles)) {
+          return TRUE;
+        }
+      }
+    }
+
+    return FALSE;
+  }
 }
 ?>
diff --git a/plugins/config/class_configInLdap.inc b/plugins/config/class_configInLdap.inc
index 31b11f220..f3bddbe0f 100644
--- a/plugins/config/class_configInLdap.inc
+++ b/plugins/config/class_configInLdap.inc
@@ -376,6 +376,29 @@ class configInLdap extends simplePlugin
             ),
             array()
           ),
+          new OrderedArrayAttribute(
+            new PipeSeparatedCompositeAttribute(
+              _('Use this to hide some menu entry to specific groups of users'),
+              'fdPluginsMenuBlacklist',
+              array(
+                new SelectAttribute(
+                  '', _('Group or role'),
+                  'blacklistGroup', TRUE,
+                  array()
+                ),
+                new SelectAttribute(
+                  '', _('Plugin to blacklist'),
+                  'blacklistPlugin', TRUE,
+                  array()
+                ),
+              ),
+              '',
+              _('Plugin menu blacklist')
+            ),
+            // no order
+            FALSE,
+            array()
+          )
         )
       ),
       'hooks' => array(
@@ -425,6 +448,7 @@ class configInLdap extends simplePlugin
 
   function __construct ($dn = NULL, $object = NULL, $parent = NULL, $mainTab = FALSE, $attributesInfo = NULL)
   {
+    global $config;
     $attributesInfo = static::getAttributesInfo();
     /* Languages */
     $languages = get_languages(TRUE);
@@ -438,6 +462,42 @@ class configInLdap extends simplePlugin
     $methods = $methods['name'];
     $attributesInfo['password']['attrs'][0]->setChoices($methods);
 
+    $groupsAndRoles = array_merge(
+      array_map(
+        function ($group)
+        {
+          return sprintf(_('Group %s'), $group);
+        },
+        objects::ls('ogroup')
+      ),
+      array_map(
+        function ($role)
+        {
+          return sprintf(_('Role %s'), $role);
+        },
+        objects::ls('role')
+      )
+    );
+    $attributesInfo['miscellaneous']['attrs'][3]->attribute->attributes[0]->setChoices(
+      array_keys($groupsAndRoles),
+      array_values($groupsAndRoles)
+    );
+    $menuPlugins = array();
+    $plist = session::global_get('plist');
+    foreach ($config->data['SECTIONS'] as $section => $section_infos) {
+      foreach ($config->data['MENU'][$section] as $info) {
+        if (isset($info['CLASS'])) {
+          list ($plHeadline, , , ) = $plist->get_infos($info['CLASS']);
+          $menuPlugins[$info['CLASS']] = $plHeadline;
+        }
+      }
+    }
+    asort($menuPlugins);
+    $attributesInfo['miscellaneous']['attrs'][3]->attribute->attributes[1]->setChoices(
+      array_keys($menuPlugins),
+      array_values($menuPlugins)
+    );
+
     try {
       parent::__construct($dn, $object, $parent, $mainTab, $attributesInfo);
     } catch (NonExistingLdapNodeException $e) {
-- 
GitLab