import main config

This commit is contained in:
Roland Gruber 2020-04-12 21:51:19 +02:00
parent 38293656b6
commit 00c5a014b4
5 changed files with 223 additions and 6 deletions

View File

@ -2705,7 +2705,7 @@ class LAMCfgMain {
logNewMessage(LOG_WARNING, 'Ignored setting during import: ' . $dataKey);
continue;
}
if (!(is_array($dataValue) || is_string($dataValue) || is_int($dataValue) || is_bool($dataValue))) {
if (!(($dataValue === null) || is_array($dataValue) || is_string($dataValue) || is_int($dataValue) || is_bool($dataValue))) {
throw new LAMException('Invalid import data type for ' . htmlspecialchars($dataKey) . ': ' . gettype($dataValue));
}
$this->$dataKey = $dataValue;

View File

@ -1,5 +1,8 @@
<?php
namespace LAM\PERSISTENCE;
use LAMCfgMain;
use LAMException;
/*
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
@ -31,7 +34,7 @@ namespace LAM\PERSISTENCE;
include_once __DIR__ . '/config.inc';
/**
* Exprter for LAM's configuration data.
* Exporter for LAM's configuration data.
*/
class ConfigDataExporter {
@ -40,7 +43,7 @@ class ConfigDataExporter {
*/
public function exportAsJson() {
$jsonData = array();
$jsonData['mainconfig'] = $this->_getMainConfigData();
$jsonData['mainConfig'] = $this->_getMainConfigData();
return json_encode($jsonData);
}
@ -50,9 +53,137 @@ class ConfigDataExporter {
* @return array data
*/
public function _getMainConfigData() {
$mainCfg = new \LAMCfgMain();
$mainCfg = new LAMCfgMain();
return $mainCfg->exportData();
}
}
/**
* Importer for LAM's configuration data.
*/
class ConfigDataImporter {
/**
* Returns a list of possible import objects.
*
* @param string $json JSON data
* @return ImporterStep[] steps
* @throws LAMException if invalid format
*/
public function getPossibleImportSteps($json) {
$data = json_decode($json);
if ($data === null) {
throw new LAMException(_('Unable to read import file.'));
}
$steps = array();
foreach ($data as $key => $value) {
switch ($key) {
case 'mainConfig':
$steps[] = new ImporterStep(_('General settings'), 'mainConfig', $value);
break;
default:
logNewMessage(LOG_WARNING, 'Unknown import type: ' . $key);
}
}
if (empty($steps)) {
throw new LAMException(_('Unable to read import file.'));
}
return $steps;
}
/**
* Runs the actual import.
*
* @param ImporterStep[] $steps import steps
* @throws LAMException if error occured
*/
public function runImport($steps) {
foreach ($steps as $step) {
if (!$step->isActive()) {
continue;
}
$key = $step->getKey();
switch ($key) {
case 'mainConfig':
$cfgMain = new LAMCfgMain();
$cfgMain->importData($step->getValue());
$cfgMain->save();
break;
default:
logNewMessage(LOG_WARNING, 'Unknown import type: ' . $key);
}
}
}
}
/**
* Step of the import process.
*/
class ImporterStep {
private $label;
private $key;
private $value;
private $active = false;
/**
* Constructor.
*
* @param string $label label
* @param string $key key
* @param array $value value
*/
public function __construct($label, $key, &$value) {
$this->label = $label;
$this->key = $key;
$this->value = $value;
}
/**
* Returns the label.
*
* @return string label
*/
public function getLabel() {
return $this->label;
}
/**
* Returns the key.
*
* @return string key
*/
public function getKey() {
return $this->key;
}
/**
* Returns if this step should be executed.
*
* @return bool active
*/
public function isActive(): bool {
return $this->active;
}
/**
* Sets if this step should be executed.
*
* @param bool $active active
*/
public function setActive(bool $active) {
$this->active = $active;
}
/**
* Returns the value.
*
* @return string value
*/
public function getValue() {
return $this->value;
}
}

View File

@ -1,13 +1,18 @@
<?php
namespace LAM\CONFIG;
use htmlButton;
use htmlInputFileUpload;
use htmlLink;
use htmlOutputText;
use htmlResponsiveInputCheckbox;
use htmlResponsiveInputField;
use htmlResponsiveRow;
use htmlStatusMessage;
use htmlSubTitle;
use LAM\PERSISTENCE\ConfigDataExporter;
use LAM\PERSISTENCE\ConfigDataImporter;
use LAMCfgMain;
use LAMException;
/*
@ -86,7 +91,7 @@ printHeaderContents(_("Import and export configuration"), '../..');
</td>
</tr>
</table>
<form action="confImportExport.php" method="post" autocomplete="off">
<form action="confImportExport.php" method="post" autocomplete="off" enctype="multipart/form-data">
<br><br>
<?php
@ -120,6 +125,7 @@ printHeaderContents(_("Import and export configuration"), '../..');
}
$pwdInput = new htmlResponsiveInputField(_("Master password"), 'password', '', '236');
$pwdInput->setIsPassword(true);
$pwdInput->setCSSClasses(array('lam-initial-focus'));
$loginContent->add($pwdInput, 12);
$loginContent->addLabel(new htmlOutputText('&nbsp;', false));
$loginContent->addField(new htmlButton('submitLogin', _("Ok")));
@ -127,8 +133,21 @@ printHeaderContents(_("Import and export configuration"), '../..');
$content->add($loginContent, 12);
parseHtml(null, $content, array(), false, $tabindex, null);
renderBackLink();
}
/**
* Renders the link back to login page.
*/
function renderBackLink() {
$tabindex = 0;
$content = new htmlResponsiveRow();
$content->addVerticalSpacer('2rem');
$content->add(new htmlLink(_('Back to login'), '../login.php', '../../graphics/undo.png'), 12);
$content->addVerticalSpacer('1rem');
parseHtml(null, $content, array(), false, $tabindex, null);
}
/**
* Checks the login password.
*
@ -158,8 +177,73 @@ printHeaderContents(_("Import and export configuration"), '../..');
$content->add(new htmlButton('exportConfig', _('Export')), 12);
$content->add(new htmlSubTitle(_('Import')), 12);
renderImportPart($content);
parseHtml(null, $content, array(), false, $tabindex, null);
renderBackLink();
}
/**
* Renders the import area.
*
* @param htmlResponsiveRow $content content where to add import part
*/
function renderImportPart($content) {
$fileContent = null;
$validUpload = false;
$importSteps = array();
if (isset($_POST['importConfig'])) {
$handle = fopen($_FILES['import-file']['tmp_name'], "r");
$data = fread($handle, 100000000);
fclose($handle);
try {
$importer = new ConfigDataImporter();
$importSteps = $importer->getPossibleImportSteps($data);
$tmpFile = __DIR__ . '/../../tmp/internal/import_' . getRandomNumber() . '.tmp';
$file = @fopen($tmpFile, "w");
if ($file) {
fputs($file, $data);
fclose($file);
chmod($tmpFile, 0600);
}
$_SESSION['configImportFile'] = $tmpFile;
$validUpload = true;
}
catch (LAMException $e) {
$content->add(new htmlStatusMessage('ERROR', $e->getTitle(), $e->getMessage()), 12);
}
}
if (!isset($_POST['importConfigConfirm']) && !$validUpload) {
$content->add(new htmlInputFileUpload('import-file'), 12);
$content->add(new htmlButton('importConfig', _('Submit')), 12);
}
elseif (isset($_POST['importConfig'])) {
$content->add(new htmlOutputText(_('Import steps')), 12);
foreach ($importSteps as $importStep) {
$content->add(new htmlResponsiveInputCheckbox('step_' . $importStep->getKey(), true, $importStep->getLabel()), 12);
}
$content->add(new htmlButton('importConfigConfirm', _('Import')), 12);
$content->add(new htmlButton('importCancel', _('Cancel')), 12);
}
elseif (isset($_POST['importConfigConfirm'])) {
$handle = fopen($_SESSION['configImportFile'], "r");
$data = fread($handle, 100000000);
fclose($handle);
try {
$importer = new ConfigDataImporter();
$importSteps = $importer->getPossibleImportSteps($data);
foreach ($importSteps as $importStep) {
$importStep->setActive(isset($_POST['step_' . $importStep->getKey()]));
}
$importer->runImport($importSteps);
unlink($_SESSION['configImportFile']);
$content->add(new htmlStatusMessage('INFO', _('Configuration import ended successful.')), 12);
}
catch (LAMException $e) {
$content->add(new htmlStatusMessage('ERROR', $e->getTitle(), $e->getMessage()), 12);
$content->add(new htmlButton('importCancel', _('Cancel')), 12);
}
}
}
?>

View File

@ -146,6 +146,7 @@ class LAMCfgMainTest extends TestCase {
$importData['sessionTimeout'] = 240;
$importData['logLevel'] = LOG_ERR;
$importData['mailServer'] = 'mailserver';
$importData['allowedHosts'] = null;
$importData['IGNORE_ME'] = 'ignore';
$this->conf->importData($importData);
@ -154,6 +155,7 @@ class LAMCfgMainTest extends TestCase {
$this->assertEquals(240, $this->conf->sessionTimeout);
$this->assertEquals(LOG_ERR, $this->conf->logLevel);
$this->assertEquals('mailserver', $this->conf->mailServer);
$this->assertNull($this->conf->allowedHosts);
}
/**

View File

@ -37,7 +37,7 @@ class ConfigDataExporterTest extends TestCase {
'confMainKey2' => 4,
'confMainKey3' => '',
);
$expectedJson = json_encode(array('mainconfig' => $mainData));
$expectedJson = json_encode(array('mainConfig' => $mainData));
$exporter = $this->getMockBuilder('\LAM\PERSISTENCE\ConfigDataExporter')
->setMethods(array('_getMainConfigData'))