From 32b5a14226ec53078ce45f4182900ba710173e45 Mon Sep 17 00:00:00 2001 From: Roland Gruber Date: Fri, 22 May 2020 21:02:13 +0200 Subject: [PATCH] import and export account profile templates --- lam/lib/persistence.inc | 46 +++++++++++++ lam/lib/profiles.inc | 80 ++++++++++++++++++----- lam/templates/config/confImportExport.php | 7 +- lam/tests/lib/persistenceTest.php | 8 ++- 4 files changed, 122 insertions(+), 19 deletions(-) diff --git a/lam/lib/persistence.inc b/lam/lib/persistence.inc index 849641aa..59274f7f 100644 --- a/lam/lib/persistence.inc +++ b/lam/lib/persistence.inc @@ -10,7 +10,10 @@ use function LAM\PDF\getAvailableLogos; use function LAM\PDF\getPDFStructures; use function LAM\PDF\uploadPDFLogo; use function LAM\PROFILES\getAccountProfiles; +use function LAM\PROFILES\getProfileTemplateNames; +use function LAM\PROFILES\installTemplateAccountProfile; use function LAM\PROFILES\loadAccountProfile; +use function LAM\PROFILES\loadTemplateAccountProfile; use function LAM\PROFILES\saveAccountProfile; /* @@ -51,6 +54,7 @@ class ConfigDataExporter { /** * Exports LAM's configuration data in JSON format. + * @throws LAMException error during export */ public function exportAsJson() { $mainCfg = $this->_getMainConfiguration(); @@ -64,6 +68,7 @@ class ConfigDataExporter { } $jsonData['serverProfiles'] = $this->_getServerProfiles($serverProfiles); $jsonData['accountProfiles'] = $this->_getAccountProfiles($serverProfiles); + $jsonData['accountProfileTemplates'] = $this->_getAccountProfileTemplates($serverProfiles); $jsonData['pdfProfiles'] = $this->_getPdfProfiles($serverProfiles); /** * TODO @@ -71,6 +76,7 @@ class ConfigDataExporter { * pdf/account templates /config/templates * self service profiles * webauthn + * cron job runs */ return json_encode($jsonData); } @@ -138,6 +144,25 @@ class ConfigDataExporter { return $data; } + /** + * Returns the content of the account profile templates. + * + * @param array $serverProfiles list of server profiles (name => object) + * @return array $data + * @throws LAMException error reading template + */ + public function _getAccountProfileTemplates($serverProfiles) { + $data = array(); + $accountProfileTemplateNames = getProfileTemplateNames(); + foreach ($accountProfileTemplateNames as $scope => $templateNames) { + foreach ($templateNames as $templateName) { + $accountProfileTemplate = loadTemplateAccountProfile($templateName, $scope); + $data[$scope][$templateName] = $accountProfileTemplate; + } + } + return $data; + } + /** * Returns the content of the PDF profiles. * @@ -210,6 +235,9 @@ class ConfigDataImporter { } $steps[] = $mainStep; break; + case 'accountProfileTemplates': + $steps[] = new ImporterStep(_('Account profiles') . ' - ' . _('Global templates'), 'accountProfileTemplates', $value); + break; case 'pdfProfiles': $mainStep = new ImporterStep(_('PDF structures'), 'pdfProfiles', $value); foreach ($value as $profileName => $profileData) { @@ -252,6 +280,9 @@ class ConfigDataImporter { case 'accountProfiles': $this->importAccountProfiles($step); break; + case 'accountProfileTemplates': + $this->importAccountProfileTemplates($step); + break; case 'pdfProfiles': $this->importPdfProfiles($step); break; @@ -339,6 +370,21 @@ class ConfigDataImporter { } } + /** + * Imports the account profile templates. + * + * @param ImporterStep $step step + * @throws LAMException error during import + */ + private function importAccountProfileTemplates($step) { + $data = $step->getValue(); + foreach ($data as $typeId => $accountProfileTemplates) { + foreach ($accountProfileTemplates as $accountProfileTemplateName => $accountProfileData) { + installTemplateAccountProfile($typeId, $accountProfileTemplateName, $accountProfileData); + } + } + } + /** * Imports the PDF profiles. * diff --git a/lam/lib/profiles.inc b/lam/lib/profiles.inc index c09d2464..a45fe0f1 100644 --- a/lam/lib/profiles.inc +++ b/lam/lib/profiles.inc @@ -1,8 +1,8 @@ read(); while ($entry){ @@ -90,7 +89,7 @@ function profileExists($name, $typeId) { function loadAccountProfile($profile, $typeId, $serverProfileName) { if (!isValidProfileName($profile) || !preg_match("/^[a-z0-9_]+$/i", $typeId)) { logNewMessage(LOG_NOTICE, "Invalid account profile name: $serverProfileName:$profile:$typeId"); - return false; + return array(); } $file = substr(__FILE__, 0, strlen(__FILE__) - 17) . "/config/profiles/" . $serverProfileName . '/' . $profile . "." . $typeId; try { @@ -98,6 +97,7 @@ function loadAccountProfile($profile, $typeId, $serverProfileName) { } catch (LAMException $e) { StatusMessage('ERROR', $e->getTitle(), $e->getMessage()); } + return array(); } /** @@ -118,7 +118,6 @@ function readAccountProfileFile($fileName) { continue; // ignore comments } // search keywords - $parts = array(); $parts = explode(": ", $line); if (sizeof($parts) == 2) { $option = $parts[0]; @@ -138,7 +137,6 @@ function readAccountProfileFile($fileName) { else { throw new LAMException(_("Unable to load profile!"), $fileName); } - return array(); } /** @@ -154,10 +152,10 @@ function readAccountProfileFile($fileName) { */ function saveAccountProfile($attributes, $profile, $typeId, $serverProfile) { // check profile name and type id - $typeManager = new \LAM\TYPES\TypeManager($serverProfile); + $typeManager = new TypeManager($serverProfile); $type = $typeManager->getConfiguredType($typeId); if (!isValidProfileName($profile) || !preg_match("/^[a-z0-9_]+$/i", $typeId) || ($type == null)) { - logNewMessage(LOG_NOTICE, 'Invalid account profile name', $profile . ':' . $typeId); + logNewMessage(LOG_NOTICE, 'Invalid account profile name: ' . $profile . ':' . $typeId); return false; } if (!is_array($attributes)) { @@ -165,13 +163,24 @@ function saveAccountProfile($attributes, $profile, $typeId, $serverProfile) { return false; } $path = substr(__FILE__, 0, strlen(__FILE__) - 17) . "/config/profiles/" . $serverProfile->getName() . '/' . $profile . "." . $typeId; - $file = @fopen($path, "w"); + return writeProfileDataToFile($path, $attributes); +} + +/** + * Writes the profile data to the given file. + * + * @param string $fileName file name + * @param array $data profile data + * @return bool writing was ok + */ +function writeProfileDataToFile($fileName, $data) { + $file = @fopen($fileName, "w"); if ($file) { - // write attributes - $keys = array_keys($attributes); + // write attributes + $keys = array_keys($data); for ($i = 0; $i < sizeof($keys); $i++) { - if (isset($attributes[$keys[$i]])) { - $line = $keys[$i] . ": " . implode("+::+", $attributes[$keys[$i]]) . "\n"; + if (isset($data[$keys[$i]])) { + $line = $keys[$i] . ": " . implode("+::+", $data[$keys[$i]]) . "\n"; } else { $line = $keys[$i] . ": \n"; @@ -182,7 +191,7 @@ function saveAccountProfile($attributes, $profile, $typeId, $serverProfile) { fclose($file); } else { - logNewMessage(LOG_NOTICE, 'Unable to open account profile file: ' . $path); + logNewMessage(LOG_NOTICE, 'Unable to open account profile file: ' . $fileName); return false; } return true; @@ -199,7 +208,7 @@ function delAccountProfile($file, $typeId) { if (!isLoggedIn()) { return false; } - $typeManager = new \LAM\TYPES\TypeManager(); + $typeManager = new TypeManager(); $type = $typeManager->getConfiguredType($typeId); if (!isValidProfileName($file) || !preg_match("/^[a-z0-9_]+$/i", $typeId) || ($type == null)) { return false; @@ -226,7 +235,7 @@ function isValidProfileName($name) { * @param \LAM\TYPES\ConfiguredType $sourceType source type * @param string $sourceProfileName profile name * @param \LAM\TYPES\ConfiguredType $targetType target type - * @throws Exception + * @throws LAMException error during copy */ function copyAccountProfile($sourceType, $sourceProfileName, $targetType) { if (!isValidProfileName($sourceProfileName)) { @@ -249,7 +258,7 @@ function copyAccountProfile($sourceType, $sourceProfileName, $targetType) { * * @param \LAM\TYPES\ConfiguredType $sourceType source type * @param string $sourceProfileName profile name - * @throws Exception + * @throws LAMException error during copy */ function copyAccountProfileToTemplates($sourceType, $sourceProfileName) { if (!isValidProfileName($sourceProfileName)) { @@ -275,7 +284,7 @@ function installProfileTemplates() { if (!file_exists($basePath)) { mkdir($basePath, 0700, true); } - $typeManager = new \LAM\TYPES\TypeManager(); + $typeManager = new TypeManager(); foreach ($typeManager->getConfiguredTypes() as $type) { if (empty($allTemplates[$type->getScope()])) { continue; @@ -326,3 +335,40 @@ function getProfileTemplateFileName($scope, $name) { return __DIR__ . '/../config/templates/profiles' . '/' . $name . '.' . $scope; } +/** + * Loads a template profile of the given account scope. + * + * @param string $profile name of the profile (without . extension) + * @param string $scope account type + * @return array hash array (attribute => value) + * @throws LAMException error reading profile template + */ +function loadTemplateAccountProfile($profile, $scope) { + if (!isValidProfileName($profile) || !preg_match("/^[a-z0-9_]+$/i", $scope)) { + logNewMessage(LOG_NOTICE, "Invalid account profile name: $profile:$scope"); + return array(); + } + $fileName = getProfileTemplateFileName($scope, $profile); + return readAccountProfileFile($fileName); +} + +/** + * Installs a single template from the given data. + * + * @param string $scope account type (e.g. user) + * @param string $name template name + * @param array $data profile data + * @throws LAMException error saving file + */ +function installTemplateAccountProfile($scope, $name, $data) { + if (!isValidProfileName($name) || !preg_match("/^[a-z0-9_]+$/i", $scope)) { + logNewMessage(LOG_NOTICE, "Invalid account profile name: $name:$scope"); + return; + } + $fileName = getProfileTemplateFileName($scope, $name); + $success = writeProfileDataToFile($fileName, $data); + if (!$success) { + throw new LAMException('Unable to write account profile template: ' . $fileName); + } +} + diff --git a/lam/templates/config/confImportExport.php b/lam/templates/config/confImportExport.php index 5bf10110..182ae2a3 100644 --- a/lam/templates/config/confImportExport.php +++ b/lam/templates/config/confImportExport.php @@ -69,7 +69,12 @@ if (isset($_POST['exportConfig']) && $cfg->checkPassword($_SESSION["mainconf_pas header('Content-Type: application/json; charset=utf-8'); header('Content-disposition: attachment; filename=lam-config.json'); } - echo $exporter->exportAsJson(); + try { + echo $exporter->exportAsJson(); + } + catch (LAMException $e) { + logNewMessage('ERROR', $e->getTitle() . ' ' . $e->getMessage()); + } exit; } diff --git a/lam/tests/lib/persistenceTest.php b/lam/tests/lib/persistenceTest.php index 36a9ddf6..3d6eb5c1 100644 --- a/lam/tests/lib/persistenceTest.php +++ b/lam/tests/lib/persistenceTest.php @@ -48,6 +48,10 @@ class ConfigDataExporterTest extends TestCase { 'group' => array('default' => array('key' => 'value')), ), ); + $accountProfileTemplateData = array( + 'user' => array('default' => array('key' => 'value')), + 'group' => array('default' => array('key' => 'value')), + ); $pdfData = array( 'profile1' => array('structures' => array( 'user' => array( @@ -63,17 +67,19 @@ class ConfigDataExporterTest extends TestCase { 'certificates' => 'certs', 'serverProfiles' => $profileData, 'accountProfiles' => $accountProfileData, + 'accountProfileTemplates' => $accountProfileTemplateData, 'pdfProfiles' => $pdfData, )); $exporter = $this->getMockBuilder('\LAM\PERSISTENCE\ConfigDataExporter') ->setMethods(array('_getMainConfigData', '_getCertificates', '_getServerProfiles', - '_getAccountProfiles', '_getPdfProfiles')) + '_getAccountProfiles', '_getAccountProfileTemplates', '_getPdfProfiles')) ->getMock(); $exporter->method('_getMainConfigData')->willReturn($mainData); $exporter->method('_getCertificates')->willReturn('certs'); $exporter->method('_getServerProfiles')->willReturn($profileData); $exporter->method('_getAccountProfiles')->willReturn($accountProfileData); + $exporter->method('_getAccountProfileTemplates')->willReturn($accountProfileTemplateData); $exporter->method('_getPdfProfiles')->willReturn($pdfData); $json = $exporter->exportAsJson();