From 7f16d648cc20f8556e41be359268f5ce4d7ed034 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 15 Jul 2021 19:11:20 +0200 Subject: [PATCH] IcingaUser: add basket support fixes #2328 --- application/controllers/UserController.php | 5 ++ application/forms/BasketForm.php | 3 + doc/82-Changelog.md | 1 + .../Automation/BasketSnapshot.php | 8 +++ library/Director/Objects/IcingaUser.php | 48 ++++++++++++- .../Director/Objects/ImportExportHelper.php | 68 +++++++++++++++++++ 6 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 library/Director/Objects/ImportExportHelper.php diff --git a/application/controllers/UserController.php b/application/controllers/UserController.php index 12f1bd90..b021be94 100644 --- a/application/controllers/UserController.php +++ b/application/controllers/UserController.php @@ -10,4 +10,9 @@ class UserController extends ObjectController { $this->assertPermission('director/users'); } + + protected function hasBasketSupport() + { + return true; + } } diff --git a/application/forms/BasketForm.php b/application/forms/BasketForm.php index 6085a683..8ff6cca6 100644 --- a/application/forms/BasketForm.php +++ b/application/forms/BasketForm.php @@ -24,6 +24,9 @@ class BasketForm extends DirectorObjectForm 'IcingaTemplateChoiceService' => $this->translate('Service Template Choice'), 'ServiceTemplate' => $this->translate('Service Templates'), 'ServiceSet' => $this->translate('Service Sets'), + 'UserGroup' => $this->translate('User Groups'), + 'UserTemplate' => $this->translate('User Templates'), + 'User' => $this->translate('Users'), 'NotificationTemplate' => $this->translate('Notification Templates'), 'Notification' => $this->translate('Notifications'), 'TimePeriod' => $this->translate('Time Periods'), diff --git a/doc/82-Changelog.md b/doc/82-Changelog.md index 2393a186..504008e9 100644 --- a/doc/82-Changelog.md +++ b/doc/82-Changelog.md @@ -18,6 +18,7 @@ next (will be 1.9.0) ### Configuration Baskets * FIX: Notification Apply Rules have not been exported (#2335) * FEATURE: it's now possible to purge objects of specific types (#2201) +* FEATURE: exporting Users, User-Templates and -Groups is now possible (#2328) ### Permissions and Restrictions * FEATURE: allow using monitoring module permissions (#2304) diff --git a/library/Director/DirectorObject/Automation/BasketSnapshot.php b/library/Director/DirectorObject/Automation/BasketSnapshot.php index 44675e8e..e43af0b2 100644 --- a/library/Director/DirectorObject/Automation/BasketSnapshot.php +++ b/library/Director/DirectorObject/Automation/BasketSnapshot.php @@ -20,6 +20,8 @@ use Icinga\Module\Director\Objects\IcingaServiceSet; use Icinga\Module\Director\Objects\IcingaTemplateChoiceHost; use Icinga\Module\Director\Objects\IcingaTemplateChoiceService; use Icinga\Module\Director\Objects\IcingaTimePeriod; +use Icinga\Module\Director\Objects\IcingaUser; +use Icinga\Module\Director\Objects\IcingaUserGroup; use Icinga\Module\Director\Objects\ImportSource; use Icinga\Module\Director\Objects\SyncRule; use InvalidArgumentException; @@ -40,6 +42,9 @@ class BasketSnapshot extends DbObject 'IcingaTemplateChoiceService' => IcingaTemplateChoiceService::class, 'ServiceTemplate' => IcingaService::class, 'ServiceSet' => IcingaServiceSet::class, + 'UserGroup' => IcingaUserGroup::class, + 'UserTemplate' => [IcingaUser::class, ['object_type' => 'template']], + 'User' => [IcingaUser::class, ['object_type' => 'object']], 'NotificationTemplate' => IcingaNotification::class, 'Notification' => [IcingaNotification::class, ['object_type' => 'apply']], 'DataList' => DirectorDatalist::class, @@ -73,6 +78,9 @@ class BasketSnapshot extends DbObject 'IcingaTemplateChoiceService', 'ServiceTemplate', 'ServiceSet', + 'UserGroup', + 'UserTemplate', + 'User', 'NotificationTemplate', 'Notification', 'Dependency', diff --git a/library/Director/Objects/IcingaUser.php b/library/Director/Objects/IcingaUser.php index c50a2312..51baae46 100644 --- a/library/Director/Objects/IcingaUser.php +++ b/library/Director/Objects/IcingaUser.php @@ -2,7 +2,11 @@ namespace Icinga\Module\Director\Objects; -class IcingaUser extends IcingaObject +use Icinga\Module\Director\Db; +use Icinga\Module\Director\DirectorObject\Automation\ExportInterface; +use Icinga\Module\Director\Exception\DuplicateKeyException; + +class IcingaUser extends IcingaObject implements ExportInterface { protected $table = 'icinga_user'; @@ -40,4 +44,46 @@ class IcingaUser extends IcingaObject 'period' => 'IcingaTimePeriod', 'zone' => 'IcingaZone', ); + + public function export() + { + return ImportExportHelper::simpleExport($this); + } + + /** + * @param $plain + * @param Db $db + * @param bool $replace + * @return IcingaUser + * @throws DuplicateKeyException + * @throws \Icinga\Exception\NotFoundError + */ + public static function import($plain, Db $db, $replace = false) + { + $properties = (array) $plain; + $key = $properties['object_name']; + + if ($replace && static::exists($key, $db)) { + $object = static::load($key, $db); + } elseif (static::exists($key, $db)) { + throw new DuplicateKeyException( + 'Cannot import, %s "%s" already exists', + static::create([])->getShortTableName(), + $key + ); + } else { + $object = static::create([], $db); + } + + // $object->newFields = $properties['fields']; + unset($properties['fields']); + $object->setProperties($properties); + + return $object; + } + + public function getUniqueIdentifier() + { + return $this->getObjectName(); + } } diff --git a/library/Director/Objects/ImportExportHelper.php b/library/Director/Objects/ImportExportHelper.php new file mode 100644 index 00000000..98d34c6d --- /dev/null +++ b/library/Director/Objects/ImportExportHelper.php @@ -0,0 +1,68 @@ +toPlainObject(); + $props['fields'] = static::fetchFields($object); + ksort($props); // TODO: ksort in toPlainObject? + + return (object) $props; + } + + public static function fetchFields(IcingaObject $object) + { + return static::loadFieldReferences( + $object->getConnection(), + $object->getShortTableName(), + $object->get('id') + ); + } + + /** + * @param Db $connection + * @param string $type Warning: this will not be validated. + * @param int $id + * @return array + */ + public static function loadFieldReferences(Db $connection, $type, $id) + { + $db = $connection->getDbAdapter(); + $res = $db->fetchAll( + $db->select()->from([ + 'f' => "icinga_${type}_field" + ], [ + 'f.datafield_id', + 'f.is_required', + 'f.var_filter', + ])->join(['df' => 'director_datafield'], 'df.id = f.datafield_id', []) + ->where("${type}_id = ?", $id) + ->order('varname ASC') + ); + + if (empty($res)) { + return []; + } + + foreach ($res as $field) { + $field->datafield_id = (int) $field->datafield_id; + } + return $res; + } +}