diff --git a/admin_configfiles.php b/admin_configfiles.php index 85c16933..2742c43a 100644 --- a/admin_configfiles.php +++ b/admin_configfiles.php @@ -43,6 +43,11 @@ if ($userinfo['change_serversettings'] == '1') { // get distro from URL param $distribution = Request::get('distribution'); + // check for possible setting + if (empty($distribution)) { + $distribution = Settings::Get('system.distribution') ?? ""; + } + $distributions_select = []; $services = []; @@ -53,6 +58,11 @@ if ($userinfo['change_serversettings'] == '1') { Response::dynamicError("Unknown distribution"); } + // update setting if different + if ($distribution != Settings::Get('system.distribution')) { + Settings::Set('system.distribution', $distribution); + } + // create configparser object $configfiles = new ConfigParser($config_dir . '/' . $distribution . ".xml"); diff --git a/install/froxlor.sql.php b/install/froxlor.sql.php index 51f177e2..7ccb1407 100644 --- a/install/froxlor.sql.php +++ b/install/froxlor.sql.php @@ -699,6 +699,7 @@ opcache.validate_timestamps'), ('system', 'froxlorusergroup', ''), ('system', 'froxlorusergroup_gid', ''), ('system', 'acmeshpath', '/root/.acme.sh/acme.sh'), + ('system', 'distribution', ''), ('api', 'enabled', '0'), ('2fa', 'enabled', '1'), ('panel', 'decimal_places', '4'), diff --git a/install/updates/froxlor/0.11/update_0.11.inc.php b/install/updates/froxlor/0.11/update_0.11.inc.php index 82712c91..ef7c5c0e 100644 --- a/install/updates/froxlor/0.11/update_0.11.inc.php +++ b/install/updates/froxlor/0.11/update_0.11.inc.php @@ -126,6 +126,8 @@ if (Froxlor::isFroxlorVersion('0.10.99')) { Update::showUpdateStep("Adding new settings"); $panel_settings_mode = isset($_POST['panel_settings_mode']) ? (int) $_POST['panel_settings_mode'] : 0; Settings::AddNew("panel.settings_mode", $panel_settings_mode); + $system_distribution = isset($_POST['system_distribution']) ? $_POST['system_distribution'] : ''; + Settings::AddNew("system.distribution", $system_distribution); Update::lastStepStatus(0); Update::showUpdateStep("Adjusting existing settings"); diff --git a/install/updates/preconfig/0.11/preconfig_0.11.inc.php b/install/updates/preconfig/0.11/preconfig_0.11.inc.php index c86d8bb2..e9a7f959 100644 --- a/install/updates/preconfig/0.11/preconfig_0.11.inc.php +++ b/install/updates/preconfig/0.11/preconfig_0.11.inc.php @@ -15,6 +15,10 @@ * */ +use Froxlor\Froxlor; +use Froxlor\FileDir; +use Froxlor\Config\ConfigParser; + /** * checks if the new-version has some updating to do * @@ -29,7 +33,6 @@ */ function parseAndOutputPreconfig011(&$has_preconfig, &$return, $current_version, $current_db_version) { - global $lng; if (versionInUpdate($current_version, '0.10.99')) { $has_preconfig = true; @@ -45,5 +48,28 @@ function parseAndOutputPreconfig011(&$has_preconfig, &$return, $current_version, 'selected' => 1, 'label' => $question ]; + + $description = 'The configuration page now can preselect a distribution, please select your current distribution'; + $return['system_distribution_note'] = ['type' => 'infotext', 'value' => $description]; + $question = 'Select distribution'; + $config_dir = FileDir::makeCorrectDir(Froxlor::getInstallDir() . '/lib/configfiles/'); + // show list of available distro's + $distros = glob($config_dir . '*.xml'); + $distributions_select[''] = '-'; + // read in all the distros + foreach ($distros as $_distribution) { + // get configparser object + $dist = new ConfigParser($_distribution); + // store in tmp array + $distributions_select[str_replace(".xml", "", strtolower(basename($_distribution)))] = $dist->getCompleteDistroName(); + } + // sort by distribution name + asort($distributions_select); + $return['system_distribution'] = [ + 'type' => 'select', + 'select_var' => $distributions_select, + 'selected' => '', + 'label' => $question + ]; } } diff --git a/lib/Froxlor/Api/Commands/ApiKeys.php b/lib/Froxlor/Api/Commands/ApiKeys.php deleted file mode 100644 index d5180e36..00000000 --- a/lib/Froxlor/Api/Commands/ApiKeys.php +++ /dev/null @@ -1,45 +0,0 @@ - - * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 - */ - -namespace Froxlor\Api\Commands; - -use Froxlor\Api\ApiCommand; - -/** - * @since 0.10.0 - */ -class ApiKeys extends ApiCommand -{ - - public function listing() - { - // - } - - public function listingCount() - { - // - } -} diff --git a/lib/Froxlor/Api/Commands/Froxlor.php b/lib/Froxlor/Api/Commands/Froxlor.php index 3cc0fb1e..f2295be1 100644 --- a/lib/Froxlor/Api/Commands/Froxlor.php +++ b/lib/Froxlor/Api/Commands/Froxlor.php @@ -296,6 +296,8 @@ class Froxlor extends ApiCommand * * @param string $module * optional, return list of functions for a specific module + * @param string $function + * optional, return parameter information for a specific module and function * * @access admin, customer * @return string json-encoded array @@ -304,6 +306,7 @@ class Froxlor extends ApiCommand public function listFunctions() { $module = $this->getParam('module', true, ''); + $function = $this->getParam('function', true, ''); $functions = []; if ($module != null) { @@ -313,11 +316,13 @@ class Froxlor extends ApiCommand $reflection = new ReflectionClass(__NAMESPACE__ . '\\' . $module); $_functions = $reflection->getMethods(ReflectionMethod::IS_PUBLIC); foreach ($_functions as $func) { - if ($func->class == __NAMESPACE__ . '\\' . $module && $func->isPublic()) { - array_push($functions, array_merge([ - 'module' => $module, - 'function' => $func->name - ], $this->getParamListFromDoc($module, $func->name))); + if (empty($function) || ($function != null && $func->name == $function)) { + if ($func->class == __NAMESPACE__ . '\\' . $module && $func->isPublic()) { + array_push($functions, array_merge([ + 'module' => $module, + 'function' => $func->name + ], $this->getParamListFromDoc($module, $func->name))); + } } } } else { diff --git a/lib/Froxlor/Cli/RunApiCommand.php b/lib/Froxlor/Cli/RunApiCommand.php index 5dd8b95e..8efcd223 100644 --- a/lib/Froxlor/Cli/RunApiCommand.php +++ b/lib/Froxlor/Cli/RunApiCommand.php @@ -29,7 +29,9 @@ use Exception; use PDO; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; use Froxlor\Database\Database; final class RunApiCommand extends CliCommand @@ -42,6 +44,7 @@ final class RunApiCommand extends CliCommand $this->addArgument('user', InputArgument::REQUIRED, 'Loginname of the user you want to run the command as') ->addArgument('api-command', InputArgument::REQUIRED, 'The command to execute in the form "Module.function"') ->addArgument('parameters', InputArgument::OPTIONAL, 'Paramaters to pass to the command as JSON array'); + $this->addOption('show-params', 's', InputOption::VALUE_NONE, 'Show possible parameters for given api-command (given command will *not* be called)'); } protected function execute(InputInterface $input, OutputInterface $output) @@ -50,26 +53,54 @@ final class RunApiCommand extends CliCommand $result = $this->validateRequirements($input, $output); - try { - $loginname = $input->getArgument('user'); - $userinfo = $this->getUserByName($loginname); - $command = $input->getArgument('api-command'); - $apicmd = $this->validateCommand($command); - $module = "\\Froxlor\\Api\\Commands\\" . $apicmd['class']; - $function = $apicmd['function']; - $params_json = $input->getArgument('parameters'); - $params = json_decode($params_json ?? '', true); - $json_result = $module::getLocal($userinfo, $params)->{$function}(); - $output->write($json_result); - $result = self::SUCCESS; - } catch (Exception $e) { - $output->writeln('' . $e->getMessage() . ''); - $result = self::FAILURE; + if ($result == self::SUCCESS) { + try { + $loginname = $input->getArgument('user'); + $userinfo = $this->getUserByName($loginname); + $command = $input->getArgument('api-command'); + $apicmd = $this->validateCommand($command); + $module = "\\Froxlor\\Api\\Commands\\" . $apicmd['class']; + $function = $apicmd['function']; + if ($input->getOption('show-params') !== false) { + $json_result = \Froxlor\Api\Commands\Froxlor::getLocal($userinfo, ['module' => $apicmd['class'], 'function' => $function])->listFunctions(); + $io = new SymfonyStyle($input, $output); + $result = $this->outputParamsList($json_result, $io); + } else { + $params_json = $input->getArgument('parameters'); + $params = json_decode($params_json ?? '', true); + $json_result = $module::getLocal($userinfo, $params)->{$function}(); + $output->write($json_result); + $result = self::SUCCESS; + } + } catch (Exception $e) { + $output->writeln('' . $e->getMessage() . ''); + $result = self::FAILURE; + } } return $result; } + private function outputParamsList(string $json, SymfonyStyle $io): int + { + $docs = json_decode($json, true); + $docs = array_shift($docs['data']); + if (!isset($docs['params'])) { + $io->warning(($docs['head'] ?? "unknown return")); + return self::INVALID; + } + if (empty($docs['params'])) { + $io->success("No parameters required"); + } else { + $rows = []; + foreach ($docs['params'] as $param) { + $rows[] = [$param['type'], '' . $param['parameter'] . '', $param['desc'] ?? ""]; + } + $io->table(['Type', 'Name', 'Description'], $rows); + } + return self::SUCCESS; + } + private function validateCommand(string $command): array { $command = explode(".", $command); diff --git a/lng/de.lng.php b/lng/de.lng.php index 3a089de4..993699d2 100644 --- a/lng/de.lng.php +++ b/lng/de.lng.php @@ -108,6 +108,7 @@ return [ 'skipconfig' => 'Nicht (erneut) konfigurieren', 'recommendednote' => 'Empfohlene/benötigte Dienste anhand der aktuellen Systemeinstellungen', 'selectrecommended' => 'Empfohlene wählen', + 'downloadselected' => 'Auswahl exportieren', ], 'templates' => [ 'templates' => 'E-Mail-Vorlagen', diff --git a/lng/en.lng.php b/lng/en.lng.php index 35885b2c..3aee9789 100644 --- a/lng/en.lng.php +++ b/lng/en.lng.php @@ -110,6 +110,7 @@ return [ 'skipconfig' => 'Don\'t (re)configure', 'recommendednote' => 'Recommended/required services based on current system settings', 'selectrecommended' => 'Select recommended', + 'downloadselected' => 'Export selected', ], 'templates' => [ 'templates' => 'Email-templates', @@ -1353,6 +1354,9 @@ Yours sincerely, your administrator', 'maintitle' => 'PHP Configurations', 'fpmdaemons' => 'PHP-FPM versions', ], + 'logger' => [ + 'logger' => 'System log', + ], ], 'message' => [ 'norecipients' => 'No e-mail has been sent because there are no recipients in the database',