From 494d36422a175a091227f147ebbb9217bd34649a Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Fri, 19 Jul 2024 17:32:18 +0200 Subject: [sysconfig] Add button to assign module to multiple configs This extends and reuses the assignment dialog that pops up at the end of the process where you create a new module. --- inc/util.inc.php | 5 +- modules-available/sysconfig/addmodule.inc.php | 53 ++++++++++++++++------ modules-available/sysconfig/inc/sysconfig.inc.php | 13 +++--- .../sysconfig/lang/de/template-tags.json | 2 + .../sysconfig/lang/en/template-tags.json | 2 + modules-available/sysconfig/page.inc.php | 1 + modules-available/sysconfig/templates/assign.html | 4 +- .../sysconfig/templates/list-legend.html | 5 ++ .../sysconfig/templates/list-modules.html | 11 +++-- 9 files changed, 70 insertions(+), 26 deletions(-) diff --git a/inc/util.inc.php b/inc/util.inc.php index 2568011b..0ff6fdad 100644 --- a/inc/util.inc.php +++ b/inc/util.inc.php @@ -15,9 +15,10 @@ class Util * * @param string|false $location Location to redirect to. "false" to redirect to same URL (useful after POSTs) * @param bool $preferRedirectPost if true, use the value from $_POST['redirect'] instead of $location + * @param bool $ignoreRedirectParams if true, ignore any additional params set via ::addRedirectParam()) */ #[NoReturn] - public static function redirect($location = false, bool $preferRedirectPost = false): void + public static function redirect($location = false, bool $preferRedirectPost = false, bool $ignoreRedirectParams = false): void { if ($location === false) { $location = preg_replace('/([&?])message\[\]=[^&]*/', '\1', $_SERVER['REQUEST_URI']); @@ -35,7 +36,7 @@ class Util $location .= '&' . $messages; } } - if (!empty(self::$redirectParams)) { + if (!$ignoreRedirectParams && !empty(self::$redirectParams)) { if (strpos($location, '?') === false) { $location .= '?' . implode('&', self::$redirectParams); } else { diff --git a/modules-available/sysconfig/addmodule.inc.php b/modules-available/sysconfig/addmodule.inc.php index 4564537e..32752c03 100644 --- a/modules-available/sysconfig/addmodule.inc.php +++ b/modules-available/sysconfig/addmodule.inc.php @@ -151,6 +151,9 @@ class AddModule_Assign extends AddModule_Base protected function preprocessInternal() { + if (!User::hasPermission('config.edit')) + Util::redirect('?do=SysConfig', false, true); + $assign = Request::any('assign', false, 'boolean'); if ($assign) { @@ -159,39 +162,51 @@ class AddModule_Assign extends AddModule_Base $moduleType = $this->edit->moduleType(); if (ConfigModule::getList()[$moduleType]['unique']) { + // Is a unique type module $moduleIds = []; foreach (ConfigModule::getAll($moduleType) ?? [] as $module) { $moduleIds[] = $module->id(); } - - Database::exec("DELETE FROM configtgz_x_module WHERE configid IN (:configids) AND moduleid IN (:moduleids)", - array('configids' => $configIds, 'moduleids' => $moduleIds)); + // First, delete all modules of given type from all involved configs + Database::exec("DELETE FROM configtgz_x_module + WHERE configid IN (:configids) + AND moduleid IN (:moduleids) + AND moduleid <> :moduleid", + ['configids' => $configIds, 'moduleids' => $moduleIds, 'moduleid' => $moduleId]); } + // Not delete module from all configs that are not selected + Database::exec("DELETE FROM configtgz_x_module WHERE moduleid = :moduleid AND configid NOT IN (:configids)", + ['configids' => $configIds, 'moduleid' => $moduleId]); + // Finally, (re)insert for all configs selected foreach ($configIds as $configId) { - Database::exec("INSERT INTO configtgz_x_module (configid, moduleid) VALUES (:configid, :moduleid)", array( + Database::exec("INSERT IGNORE INTO configtgz_x_module (configid, moduleid) VALUES (:configid, :moduleid)", array( 'configid' => $configId, 'moduleid' => $moduleId )); - ConfigTgz::get($configId)->generate(); + $config = ConfigTgz::get($configId); + $config->markOutdated(); + $config->generate(); } - Util::redirect('?do=SysConfig'); + Util::redirect('?do=SysConfig', false, true); } } protected function renderInternal() { $data = ['configs' => SysConfig::getAll()]; - if (count($data['configs']) === 0) - Util::redirect('?do=SysConfig'); + if (count($data['configs']) === 0) // Nothing to do + Util::redirect('?do=SysConfig', false, true); $moduleType = $this->edit->moduleType(); + // If this is a module of type unique, mark all configs that already contain a module of that type if (ConfigModule::getList()[$moduleType]['unique']) { - $modules = Database::queryAll('SELECT configtgz_module.moduleid as moduleid, configtgz_module.title as title, configtgz_x_module.configid as configid' - . ' FROM configtgz_module INNER JOIN configtgz_x_module ON configtgz_module.moduleid = configtgz_x_module.moduleid' - . ' WHERE configtgz_module.moduletype = :moduletype', - array('moduletype' => $moduleType)); + $modules = Database::queryAll("SELECT cm.moduleid as moduleid, cm.title as title, cxm.configid as configid + FROM configtgz_module cm + INNER JOIN configtgz_x_module cxm ON (cm.moduleid = cxm.moduleid) + WHERE cm.moduletype = :moduletype AND cxm.moduleid <> :moduleid", + ['moduletype' => $moduleType, 'moduleid' => $this->edit->id()]); $modulesByConfigId = []; foreach ($modules as $module) { @@ -199,12 +214,24 @@ class AddModule_Assign extends AddModule_Base } foreach ($data['configs'] as &$config) { - if (!isset($modulesByConfigId[$config['configid']])) continue; + if (!isset($modulesByConfigId[$config['configid']])) + continue; $config['replaces'] = $modulesByConfigId[$config['configid']]['title']; } } + // Pre-check those that are already included + $tgzs = []; + foreach (ConfigTgz::getAllForModule($this->edit->id()) as $tgz) { + $tgzs[$tgz->id()] = 1; + } + foreach ($data['configs'] as &$config) { + if (!isset($tgzs[$config['configid']])) + continue; + $config['checked'] = 'checked'; + } $data['edit'] = $this->edit->id(); + $data['name'] = $this->edit->title(); Render::addDialog(Dictionary::translate('lang_moduleAssign'), false, 'assign', $data); } diff --git a/modules-available/sysconfig/inc/sysconfig.inc.php b/modules-available/sysconfig/inc/sysconfig.inc.php index 09860c7d..362ce1a9 100644 --- a/modules-available/sysconfig/inc/sysconfig.inc.php +++ b/modules-available/sysconfig/inc/sysconfig.inc.php @@ -3,15 +3,14 @@ class SysConfig { + /** + * @return array{array{configid: int, title: string, filepath: string, status: string, locs: string}} + */ public static function getAll(): array { - $res = Database::simpleQuery("SELECT c.configid, c.title, c.filepath, c.status, Group_Concat(cl.locationid) AS locs FROM configtgz c" - . " LEFT JOIN configtgz_location cl USING (configid) GROUP BY c.configid"); - $ret = array(); - foreach ($res as $row) { - $ret[] = $row; - } - return $ret; + return Database::queryAll("SELECT c.configid, c.title, c.filepath, c.status, Group_Concat(cl.locationid) AS locs + FROM configtgz c + LEFT JOIN configtgz_location cl USING (configid) GROUP BY c.configid"); } public static function archiveContentsFromTask($status, &$userGroupWarn = null) : array diff --git a/modules-available/sysconfig/lang/de/template-tags.json b/modules-available/sysconfig/lang/de/template-tags.json index edff726c..d547d4cc 100644 --- a/modules-available/sysconfig/lang/de/template-tags.json +++ b/modules-available/sysconfig/lang/de/template-tags.json @@ -9,6 +9,8 @@ "lang_adText3": "Normalerweise k\u00f6nnen Sie als Bind DN die Kurzform im Format dom\u00e4ne\\benutzer angeben. Wenn dies nicht funktioniert, m\u00fcssen Sie den DN des Benutzers ermitteln. Z.B. unter Eingabe des folgenden Befehls auf einem DC:", "lang_adText4": "Nach Eingabe aller ben\u00f6tigten Daten wird im n\u00e4chsten Schritt \u00fcberpr\u00fcft, ob die Kommunikation mit dem AD m\u00f6glich ist.", "lang_add": "Hinzuf\u00fcgen", + "lang_assignToConfigs": "Zuweisung zu Konfigurationen \u00e4ndern", + "lang_assignToConfigsLong": "Mit dieser Funktion k\u00f6nnen sie f\u00fcr ein Modul direkt die Zuweisung zu mehreren Konfigurationen \u00e4ndern.", "lang_asteriskMandatory": "Mit (*) gekennzeichnete Felder sind Pflichtfelder", "lang_availableModules": "Verf\u00fcgbare Konfigurationsmodule", "lang_availableSystem": "Verf\u00fcgbare Systemkonfigurationen", diff --git a/modules-available/sysconfig/lang/en/template-tags.json b/modules-available/sysconfig/lang/en/template-tags.json index abb65d31..cb5e973e 100644 --- a/modules-available/sysconfig/lang/en/template-tags.json +++ b/modules-available/sysconfig/lang/en/template-tags.json @@ -9,6 +9,8 @@ "lang_adText3": "Next the distinguished name of the user must be specified. You can determine this by dsquery command line program on a domain controller as the following call:", "lang_adText4": "After entering all required data in the next step, it checks whether communication is possible with the AD.", "lang_add": "Add", + "lang_assignToConfigs": "Assign\/unassign module to configurations", + "lang_assignToConfigsLong": "Change assignment of module to multiple configurations.", "lang_asteriskMandatory": "Fields marked with (*) are mandatory", "lang_availableModules": "Available Configuration Modules", "lang_availableSystem": "Available System Configuration", diff --git a/modules-available/sysconfig/page.inc.php b/modules-available/sysconfig/page.inc.php index 9f816e30..c015d059 100644 --- a/modules-available/sysconfig/page.inc.php +++ b/modules-available/sysconfig/page.inc.php @@ -246,6 +246,7 @@ class Page_SysConfig extends Page 'havemodules' => (count($modules) > 0) ); Permission::addGlobalTags($data['perms'], null, ['module.edit', 'module.download']); + Permission::addGlobalTags($data['perms'], null, ['config.edit']); Render::addTemplate('list-modules', $data); } diff --git a/modules-available/sysconfig/templates/assign.html b/modules-available/sysconfig/templates/assign.html index 9e83f965..f06b581e 100644 --- a/modules-available/sysconfig/templates/assign.html +++ b/modules-available/sysconfig/templates/assign.html @@ -3,11 +3,13 @@ +
+ + + {{lang_assignToConfigsLong}} +
{{lang_deleteLong}} diff --git a/modules-available/sysconfig/templates/list-modules.html b/modules-available/sysconfig/templates/list-modules.html index 5bd19446..9f2ee872 100644 --- a/modules-available/sysconfig/templates/list-modules.html +++ b/modules-available/sysconfig/templates/list-modules.html @@ -39,9 +39,14 @@ - + href="?do=SysConfig&action=addmodule&step={{moduleType}}_Start&edit={{id}}" + title="{{lang_edit}}"> + + + +