From 5f53704b8a35747bc5d030f43647c7ed3c8eeb28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= <come.chilliet@fusiondirectory.org> Date: Thu, 29 Oct 2020 16:54:30 +0100 Subject: [PATCH] :sparkles: feat(templates) Add incremental modifier This modifier stores a value in LDAP configuration object to make sure to always increment it each time the template is used. issue #6102 --- contrib/openldap/core-fd-conf.schema | 8 ++++ include/class_Lock.inc | 30 +++++++++++++- include/class_templateHandling.inc | 56 +++++++++++++++++++++++++++ plugins/config/class_configInLdap.inc | 1 + 4 files changed, 94 insertions(+), 1 deletion(-) diff --git a/contrib/openldap/core-fd-conf.schema b/contrib/openldap/core-fd-conf.schema index 32291dc1f..a27f7f722 100644 --- a/contrib/openldap/core-fd-conf.schema +++ b/contrib/openldap/core-fd-conf.schema @@ -425,6 +425,13 @@ attributetype ( 1.3.6.1.4.1.38414.8.18.12 NAME 'fdAclTargetFilterLimit' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +attributetype ( 1.3.6.1.4.1.38414.8.18.13 NAME 'fdIncrementalModifierStates' + DESC 'FusionDirectory - States of the incremental modifier intances, with keys value and date, encoded as JSON' + EQUALITY caseExactMatch + SUBSTR caseExactSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE ) + # Plugins attributetype ( 1.3.6.1.4.1.38414.8.19.1 NAME 'fdOGroupRDN' @@ -610,6 +617,7 @@ objectclass ( 1.3.6.1.4.1.38414.8.2.1 NAME 'fusionDirectoryConf' fdTabHook $ fdShells $ fdDefaultShell $ fdDisplayHookOutput $ fdPluginsMenuBlacklist $ fdManagementConfig $ fdManagementUserConfig $ fdAclTabOnObjects $ fdDepartmentCategories $ fdAclTargetFilterLimit $ + fdIncrementalModifierStates $ fdSslCaCertPath $ fdSslKeyPath $ fdSslCertPath $ fdCasActivated $ fdCasServerCaCertPath $ fdCasHost $ fdCasPort $ fdCasContext $ fdLoginMethod diff --git a/include/class_Lock.inc b/include/class_Lock.inc index 3b1a110d1..0e370eefc 100644 --- a/include/class_Lock.inc +++ b/include/class_Lock.inc @@ -38,7 +38,7 @@ class Lock * \brief Add a lock for object(s) * * Adds a lock by the specified user for one ore multiple objects. - * If the lock for that object already exists, an error is triggered. + * If a lock for that object already exists from another user, an error is triggered. * * \param array $object The object or array of objects to lock * @@ -267,6 +267,34 @@ class Lock return $locks; } + + /*! + * \brief Add a lock for object(s) or fail + * + * Adds a lock by the specified user for one ore multiple objects. + * If the lock for that object already exists, waits a bit and retry. + * If a lock cannot be set, throws. + * + * \param array|string $object The object or array of objects to lock + * + * \param string $user The user who shall own the lock + * + * \param int $retries how many times we can retry (waiting a second each time) + */ + public static function addOrFail ($object, string $user = NULL, int $retries = 10) + { + $wait = $retries; + while (!empty($locks = Lock::get($object))) { + sleep(1); + + /* Oups - timed out */ + if ($wait-- == 0) { + throw new FusionDirectoryException(_('Timeout while waiting for lock!')); + } + } + Lock::add($object, $user); + } + /*! * \brief Generate a lock message * diff --git a/include/class_templateHandling.inc b/include/class_templateHandling.inc index 18b382a45..1ccf38406 100644 --- a/include/class_templateHandling.inc +++ b/include/class_templateHandling.inc @@ -436,6 +436,11 @@ class templateHandling return [$dateObject->format($args[1])]; } + /* + First parameter is whether the number should always be there or only in case of duplicates (1 or 0, defaults to 0). + Second parameter is starting number, defaults to 1. + Third parameter is step, defaults to 1. + */ private static function modifierNumber (array $args) { if (count($args) < 1) { @@ -462,6 +467,53 @@ class templateHandling return $numberGenerator($args[0], $args[1], $args[2]); } + /* + Modifier parameters: + * id + * starting number, defaults to 1. + * step, defaults to 1. + */ + private static function modifierIncremental (array $args): array + { + global $config; + + if (count($args) < 1) { + throw new FusionDirectoryException(_('Missing id parameter for incremental modifier')); + } + if (count($args) < 2) { + $args[] = 1; + } + if (count($args) < 3) { + $args[] = 1; + } + $configDn = CONFIGRDN.$config->current['BASE']; + Lock::addOrFail($configDn); + $tabObject = objects::open($configDn, 'configuration'); + $json = $tabObject->getBaseObject()->fdIncrementalModifierStates; + if (empty($json)) { + $modifierStates = []; + } else { + $modifierStates = json_decode($json, TRUE); + } + if (isset($modifierStates[$args[0]])) { + $value = $modifierStates[$args[0]]['value'] + $args[2]; + } else { + $value = $args[1]; + } + $modifierStates[$args[0]] = [ + 'value' => $value, + 'date' => date('Y-m-d'), + ]; + $tabObject->getBaseObject()->fdIncrementalModifierStates = json_encode($modifierStates); + $errors = $tabObject->save(); + Lock::deleteByObject($configDn); + if (!empty($errors)) { + throw $errors[0]; + } + + return [$value]; + } + private static function modifierTitleCase ($str) { return [mb_convert_case($str, MB_CASE_TITLE, 'UTF-8')]; @@ -581,6 +633,10 @@ class templateHandling // title case $result = static::modifierTitleCase($str); break; + case 'e': + // incremental number + $result = static::modifierIncremental($args); + break; default: trigger_error("Unkown modifier '$m'"); $result = [$str]; diff --git a/plugins/config/class_configInLdap.inc b/plugins/config/class_configInLdap.inc index 456e4d76c..8c5bac2cf 100644 --- a/plugins/config/class_configInLdap.inc +++ b/plugins/config/class_configInLdap.inc @@ -72,6 +72,7 @@ class configInLdap extends simplePlugin ['America/New_York'] ), new HiddenAttribute('fusionConfigMd5'), + new HiddenAttribute('fdIncrementalModifierStates'), ] ], 'core_settings' => [ -- GitLab