From 49d6b681fda0c0e7439bb5aa7122d357ba0c3afe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=B4me=20Chilliet?= <come@opensides.be>
Date: Thu, 19 Apr 2018 11:36:51 +0200
Subject: [PATCH] :sparkles: feat(core) Add config option to follow wildcard
 foreign keys

When moving a node with subnodes, like a departement, this will use a
 filter like member=* to get references, meaning it will open all groups
 and roles and other objects which may reference DNs to make sure the
 foreign key is applied and the new DN is stored.
This will be slow if there are a lot of those objects.
Impacted fields are member, manager, roleOccupant and owner.
This is needed because they do not allow SUBSTR searches by schema
 definition.

issue #5799
---
 contrib/openldap/core-fd-conf.schema           |  8 +++++++-
 include/simpleplugin/class_simplePlugin.inc    |  7 +++++++
 plugins/admin/departments/class_country.inc    |  2 +-
 plugins/admin/departments/class_dcObject.inc   |  2 +-
 plugins/admin/departments/class_department.inc |  2 +-
 plugins/admin/departments/class_domain.inc     |  2 +-
 plugins/admin/departments/class_locality.inc   |  2 +-
 .../admin/departments/class_organization.inc   |  2 +-
 plugins/admin/groups/class_ogroup.inc          | 18 +++++++++---------
 plugins/admin/groups/class_roleGeneric.inc     |  2 +-
 plugins/config/class_configInLdap.inc          |  5 +++++
 plugins/personal/generic/class_user.inc        |  2 +-
 12 files changed, 36 insertions(+), 18 deletions(-)

diff --git a/contrib/openldap/core-fd-conf.schema b/contrib/openldap/core-fd-conf.schema
index b2831c699..840d1ff2b 100644
--- a/contrib/openldap/core-fd-conf.schema
+++ b/contrib/openldap/core-fd-conf.schema
@@ -229,6 +229,12 @@ attributetype ( 1.3.6.1.4.1.38414.8.14.7 NAME 'fdLdapSizeLimit'
   SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
   SINGLE-VALUE)
 
+attributetype ( 1.3.6.1.4.1.38414.8.14.8 NAME 'fdWildcardForeignKeys'
+  DESC 'FusionDirectory - Weither or not to enable wildcard searches for foreign keys on dn'
+  EQUALITY booleanMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
+  SINGLE-VALUE )
+
 # Login and session
 
 attributetype ( 1.3.6.1.4.1.38414.8.15.1 NAME 'fdLoginAttribute'
@@ -548,7 +554,7 @@ objectclass ( 1.3.6.1.4.1.38414.8.2.1 NAME 'fusionDirectoryConf'
     fdHandleExpiredAccounts $ fdSaslRealm $ fdSaslExop $
     fdForcePasswordDefaultHash $
     fdListSummary $
-    fdModificationDetectionAttribute $ fdLogging $ fdLdapSizeLimit $
+    fdModificationDetectionAttribute $ fdLogging $ fdLdapSizeLimit $ fdWildcardForeignKeys $
     fdLoginAttribute $ fdForceSSL $ fdWarnSSL $ fdStoreFilterSettings $ fdSessionLifeTime $
     fdHttpAuthActivated $ fdHttpHeaderAuthActivated $ fdHttpHeaderAuthHeaderName $
     fdDisplayErrors $ fdLdapMaxQueryTime $ fdLdapStats $ fdDebugLevel $
diff --git a/include/simpleplugin/class_simplePlugin.inc b/include/simpleplugin/class_simplePlugin.inc
index 811f4fd12..4853b6463 100644
--- a/include/simpleplugin/class_simplePlugin.inc
+++ b/include/simpleplugin/class_simplePlugin.inc
@@ -1563,6 +1563,13 @@ class simplePlugin
         $ofield     = $ref[1];
         $filter     = $ref[2];
         $filtersub  = $ref[3];
+        if ($filtersub == '*') {
+          if ($config->get_cfg_value('wildcardForeignKeys', 'TRUE') == 'TRUE') {
+            $filtersub = $ofield.'=*';
+          } else {
+            continue;
+          }
+        }
         if ($class == 'aclAssignment') {
           /* Special case: aclAssignment foreignKey is ignored on department types as it’s handled by the aclAssignment objectType */
           $objectTypes = array('ACLASSIGNMENT');
diff --git a/plugins/admin/departments/class_country.inc b/plugins/admin/departments/class_country.inc
index 9003206e6..ddc06d92b 100644
--- a/plugins/admin/departments/class_country.inc
+++ b/plugins/admin/departments/class_country.inc
@@ -38,7 +38,7 @@ class country extends department
         'mainAttr'    => static::$namingAttr,
       )),
       'plForeignKeys'  => array(
-        'manager' => 'user'
+        'manager' => array('user','dn','manager=%oldvalue%','*')
       ),
 
       'plProvidedAcls' => parent::generatePlProvidedAcls(static::getAttributesInfo())
diff --git a/plugins/admin/departments/class_dcObject.inc b/plugins/admin/departments/class_dcObject.inc
index 8f474083a..ced37a4e7 100644
--- a/plugins/admin/departments/class_dcObject.inc
+++ b/plugins/admin/departments/class_dcObject.inc
@@ -39,7 +39,7 @@ class dcObject extends department
         'mainAttr'    => static::$namingAttr,
       )),
       'plForeignKeys'  => array(
-        'manager' => 'user'
+        'manager' => array('user','dn','manager=%oldvalue%','*')
       ),
 
       'plProvidedAcls' => parent::generatePlProvidedAcls(static::getAttributesInfo())
diff --git a/plugins/admin/departments/class_department.inc b/plugins/admin/departments/class_department.inc
index 2fdec7cf8..319f1fc74 100644
--- a/plugins/admin/departments/class_department.inc
+++ b/plugins/admin/departments/class_department.inc
@@ -45,7 +45,7 @@ class department extends simplePlugin
           )
         ),
       'plForeignKeys'  => array(
-        'manager' => 'user'
+        'manager' => array('user','dn','manager=%oldvalue%','*')
       ),
 
       'plProvidedAcls' => parent::generatePlProvidedAcls(static::getAttributesInfo())
diff --git a/plugins/admin/departments/class_domain.inc b/plugins/admin/departments/class_domain.inc
index 31a594a1a..01994317c 100644
--- a/plugins/admin/departments/class_domain.inc
+++ b/plugins/admin/departments/class_domain.inc
@@ -39,7 +39,7 @@ class domain extends department
         'mainAttr'    => static::$namingAttr,
       )),
       'plForeignKeys'  => array(
-        'manager' => 'user'
+        'manager' => array('user','dn','manager=%oldvalue%','*')
       ),
 
       'plProvidedAcls' => parent::generatePlProvidedAcls(static::getAttributesInfo())
diff --git a/plugins/admin/departments/class_locality.inc b/plugins/admin/departments/class_locality.inc
index aadf10962..6f0e8125b 100644
--- a/plugins/admin/departments/class_locality.inc
+++ b/plugins/admin/departments/class_locality.inc
@@ -39,7 +39,7 @@ class locality extends department
         'mainAttr'    => static::$namingAttr,
       )),
       'plForeignKeys'  => array(
-        'manager' => 'user'
+        'manager' => array('user','dn','manager=%oldvalue%','*')
       ),
 
       'plProvidedAcls' => parent::generatePlProvidedAcls(static::getAttributesInfo())
diff --git a/plugins/admin/departments/class_organization.inc b/plugins/admin/departments/class_organization.inc
index 89b2c2d39..d633dc3f2 100644
--- a/plugins/admin/departments/class_organization.inc
+++ b/plugins/admin/departments/class_organization.inc
@@ -39,7 +39,7 @@ class organization extends department
         'mainAttr'    => static::$namingAttr,
       )),
       'plForeignKeys'  => array(
-        'manager' => 'user'
+        'manager' => array('user','dn','manager=%oldvalue%','*')
       ),
 
       'plProvidedAcls' => parent::generatePlProvidedAcls(static::getAttributesInfo())
diff --git a/plugins/admin/groups/class_ogroup.inc b/plugins/admin/groups/class_ogroup.inc
index a5001c471..2dcca5042 100644
--- a/plugins/admin/groups/class_ogroup.inc
+++ b/plugins/admin/groups/class_ogroup.inc
@@ -186,17 +186,17 @@ class ogroup extends simplePlugin
       )),
       'plForeignKeys'  => array(
         'member' => array(
-          array('user'),
-          array('ogroup'),
-          array('application'),
-          array('serverGeneric'),
-          array('workstationGeneric'),
-          array('terminalGeneric'),
-          array('phoneGeneric'),
-          array('printGeneric'),
+          array('user',               'dn','member=%oldvalue%','*'),
+          array('ogroup',             'dn','member=%oldvalue%','*'),
+          array('application',        'dn','member=%oldvalue%','*'),
+          array('serverGeneric',      'dn','member=%oldvalue%','*'),
+          array('workstationGeneric', 'dn','member=%oldvalue%','*'),
+          array('terminalGeneric',    'dn','member=%oldvalue%','*'),
+          array('phoneGeneric',       'dn','member=%oldvalue%','*'),
+          array('printGeneric',       'dn','member=%oldvalue%','*'),
         ),
         'owner' => array(
-          array('user'),
+          array('user','dn','owner=%oldvalue%','*')
         )
       ),
 
diff --git a/plugins/admin/groups/class_roleGeneric.inc b/plugins/admin/groups/class_roleGeneric.inc
index d4a2939f7..5441206a7 100644
--- a/plugins/admin/groups/class_roleGeneric.inc
+++ b/plugins/admin/groups/class_roleGeneric.inc
@@ -65,7 +65,7 @@ class roleGeneric extends simplePlugin
         )
       ),
       'plForeignKeys'  => array(
-        'roleOccupant' => 'user'
+        'roleOccupant' => array('user','dn','roleOccupant=%oldvalue%','*')
       ),
 
       'plProvidedAcls'  => parent::generatePlProvidedAcls(static::getAttributesInfo())
diff --git a/plugins/config/class_configInLdap.inc b/plugins/config/class_configInLdap.inc
index a8a346089..336b64ce9 100644
--- a/plugins/config/class_configInLdap.inc
+++ b/plugins/config/class_configInLdap.inc
@@ -142,6 +142,11 @@ class configInLdap extends simplePlugin
             'fdSnapshotBase', FALSE,
             'ou=snapshots,'.$config->current['BASE']
           ),
+          new BooleanAttribute (
+            _('Wildcard foreign keys'), _('Enables wildcard searches like member=* when moving a whole departement. This will open all existing groups and roles to make sure foreign keys are respected. Slow on big trees.'),
+            'fdWildcardForeignKeys', FALSE,
+            TRUE
+          ),
         )
       ),
       'password' => array(
diff --git a/plugins/personal/generic/class_user.inc b/plugins/personal/generic/class_user.inc
index 5d69d4f97..231cf96f6 100644
--- a/plugins/personal/generic/class_user.inc
+++ b/plugins/personal/generic/class_user.inc
@@ -290,7 +290,7 @@ class user extends simplePlugin
         'ou'          => get_ou('userRDN'),
       )),
       'plForeignKeys'  => array(
-        'manager' => array('user','dn')
+        'manager' => array('user','dn','manager=%oldvalue%','*')
       ),
 
       'plProvidedAcls' => array_merge(
-- 
GitLab