From d784ad7e4e3d51895341ca5ca2bcff1510065ebd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=B4me=20Chilliet?= <come@opensides.be>
Date: Tue, 16 Apr 2019 15:05:31 +0200
Subject: [PATCH] :sparkles: feat(management) Allow user to store their column
 configuration in the LDAP

issue #5966
---
 contrib/openldap/core-fd-conf.schema          |  8 ++-
 include/class_config.inc                      | 50 +++++++++++++++----
 .../class_ManagementConfigurationDialog.inc   | 16 +++++-
 3 files changed, 62 insertions(+), 12 deletions(-)

diff --git a/contrib/openldap/core-fd-conf.schema b/contrib/openldap/core-fd-conf.schema
index e776dda15..c702ec94f 100644
--- a/contrib/openldap/core-fd-conf.schema
+++ b/contrib/openldap/core-fd-conf.schema
@@ -394,6 +394,12 @@ attributetype ( 1.3.6.1.4.1.38414.8.18.10 NAME 'fdManagementConfig'
   SUBSTR caseIgnoreSubstringsMatch
   SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
 
+attributetype ( 1.3.6.1.4.1.38414.8.18.11 NAME 'fdManagementUserConfig'
+  DESC 'FusionDirectory - Per user configuration for management classes'
+  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'
@@ -576,7 +582,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 $ fdManagementConfig $
+    fdPluginsMenuBlacklist $ fdManagementConfig $ fdManagementUserConfig $
     fdAclTabOnObjects $ fdDepartmentCategories $
     fdSslCaCertPath $ fdSslKeyPath $ fdSslCertPath $
     fdCasActivated $ fdCasServerCaCertPath $ fdCasHost $ fdCasPort $ fdCasContext $
diff --git a/include/class_config.inc b/include/class_config.inc
index fa553eb2b..3ed86da24 100644
--- a/include/class_config.inc
+++ b/include/class_config.inc
@@ -521,39 +521,67 @@ class config
       }
       $this->current['MANAGEMENTCONFIG'] = $value;
     }
+    if (isset($this->current['MANAGEMENTUSERCONFIG'])) {
+      if (!is_array($this->current['MANAGEMENTUSERCONFIG'])) {
+        $this->current['MANAGEMENTUSERCONFIG'] = [$this->current['MANAGEMENTUSERCONFIG']];
+      }
+      $value = [];
+      foreach ($this->current['MANAGEMENTUSERCONFIG'] as $config) {
+        list($user, $class, $json) = explode(':', $config, 3);
+        $value[$user][$class] = $json;
+      }
+      $this->current['MANAGEMENTUSERCONFIG'] = $value;
+    }
   }
 
   /*!
    * \brief Update the management config in the LDAP and the cache
    */
-  public function updateManagementConfig ($managementClass, $managementConfig)
+  public function updateManagementConfig (string $managementClass, array $managementConfig, bool $userConfig = FALSE): array
   {
+    global $ui;
+
     $managementConfig = json_encode($managementConfig);
     $changes = [];
-    if (isset($this->current['MANAGEMENTCONFIG'][$managementClass])) {
+    if ($userConfig) {
+      if (!isset($this->current['MANAGEMENTUSERCONFIG'][$ui->dn])) {
+        $this->current['MANAGEMENTUSERCONFIG'][$ui->dn] = [];
+      }
+      $currentConfig  =& $this->current['MANAGEMENTUSERCONFIG'][$ui->dn];
+      $attrib         = 'fdManagementUserConfig';
+      $prefix         = $ui->dn.':'.$managementClass;
+    } else {
+      if (!isset($this->current['MANAGEMENTCONFIG'])) {
+        $this->current['MANAGEMENTCONFIG'] = [];
+      }
+      $currentConfig  =& $this->current['MANAGEMENTCONFIG'];
+      $attrib         = 'fdManagementConfig';
+      $prefix         = $managementClass;
+    }
+    if (isset($currentConfig[$managementClass])) {
       /* If there already was a config for this class, remove it */
-      if ($this->current['MANAGEMENTCONFIG'][$managementClass] == $managementConfig) {
+      if ($currentConfig[$managementClass] == $managementConfig) {
         /* Unless it's the same one and we've got nothing to do */
         return [];
       }
       $changes[] = [
-        'attrib'  => 'fdManagementConfig',
+        'attrib'  => $attrib,
         'modtype' => LDAP_MODIFY_BATCH_REMOVE,
-        'values'  => [$managementClass.':'.$this->current['MANAGEMENTCONFIG'][$managementClass]],
+        'values'  => [$prefix.':'.$currentConfig[$managementClass]],
       ];
     }
     /* Add the new one */
     $changes[] = [
-      'attrib'  => 'fdManagementConfig',
+      'attrib'  => $attrib,
       'modtype' => LDAP_MODIFY_BATCH_ADD,
-      'values'  => [$managementClass.':'.$managementConfig],
+      'values'  => [$prefix.':'.$managementConfig],
     ];
     $ldap = $this->get_ldap_link();
     $ldap->cd(CONFIGRDN.$this->current['BASE']);
     if (!$ldap->modify_batch($changes)) {
       return [$ldap->get_error()];
     }
-    $this->current['MANAGEMENTCONFIG'][$managementClass] = $managementConfig;
+    $currentConfig[$managementClass] = $managementConfig;
     return [];
   }
 
@@ -562,7 +590,11 @@ class config
    */
   public function getManagementConfig ($managementClass)
   {
-    if (isset($this->current['MANAGEMENTCONFIG'][$managementClass])) {
+    global $ui;
+
+    if (isset($this->current['MANAGEMENTUSERCONFIG'][$ui->dn][$managementClass])) {
+      return json_decode($this->current['MANAGEMENTUSERCONFIG'][$ui->dn][$managementClass], TRUE);
+    } elseif (isset($this->current['MANAGEMENTCONFIG'][$managementClass])) {
       return json_decode($this->current['MANAGEMENTCONFIG'][$managementClass], TRUE);
     } else {
       return NULL;
diff --git a/include/management/class_ManagementConfigurationDialog.inc b/include/management/class_ManagementConfigurationDialog.inc
index 737b8e761..9d3b0ea7d 100644
--- a/include/management/class_ManagementConfigurationDialog.inc
+++ b/include/management/class_ManagementConfigurationDialog.inc
@@ -83,7 +83,13 @@ class ManagementConfigurationDialog extends ManagementDialog
             TRUE // edition
           ),
           new BooleanAttribute(
-            _('Persitent'), _('Should this configuration be saved in the LDAP as the default configuration for this management page'),
+            _('Persitent'), _('Should this configuration be saved in the LDAP as your default configuration for this management page'),
+            'saveInLdapUser', FALSE,
+            FALSE,
+            'ManagementConfiguration'
+          ),
+          new BooleanAttribute(
+            _('Global default'), _('Should this configuration be saved in the LDAP as the default configuration for this management page for all users'),
             'saveInLdap', FALSE,
             FALSE,
             'fdManagementConfig'
@@ -123,7 +129,9 @@ class ManagementConfigurationDialog extends ManagementDialog
   {
     global $config, $ui;
 
-    if (($attr === 'managementColumns') || (is_object($attr) && ($attr->getLdapName() == 'managementColumns'))) {
+    $noAclAttrs = ['managementColumns', 'saveInLdapUser'];
+
+    if ((is_object($attr) && in_array($attr->getLdapName(), $noAclAttrs)) || in_array($attr, $noAclAttrs)) {
       return TRUE;
     } elseif (($attr === 'saveInLdap') || (is_object($attr) && ($attr->getLdapName() == 'saveInLdap'))) {
       $acl = $ui->get_permissions(CONFIGRDN.$config->current['BASE'], 'configuration/configInLdap', 'fdManagementConfig', $this->readOnly());
@@ -165,6 +173,10 @@ class ManagementConfigurationDialog extends ManagementDialog
     }
     $this->parent->setColumnConfiguration($columnInfos);
 
+    if ($this->saveInLdapUser) {
+      return $config->updateManagementConfig(get_class($this->parent), $columnInfos, TRUE);
+    }
+
     if ($this->saveInLdap) {
       return $config->updateManagementConfig(get_class($this->parent), $columnInfos);
     }
-- 
GitLab