added new cli command froxlor:user for unlocking, password-changing and info-display of a user
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
This commit is contained in:
@@ -34,6 +34,7 @@ use Froxlor\Cli\SwitchServerIp;
|
||||
use Froxlor\Cli\UpdateCommand;
|
||||
use Froxlor\Cli\InstallCommand;
|
||||
use Froxlor\Cli\MasterCron;
|
||||
use Froxlor\Cli\UserCommand;
|
||||
use Froxlor\Froxlor;
|
||||
|
||||
// validate correct php version
|
||||
@@ -57,4 +58,5 @@ $application->add(new SwitchServerIp());
|
||||
$application->add(new UpdateCommand());
|
||||
$application->add(new InstallCommand());
|
||||
$application->add(new MasterCron());
|
||||
$application->add(new UserCommand());
|
||||
$application->run();
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
namespace Froxlor\Cli;
|
||||
|
||||
use PDO;
|
||||
use Exception;
|
||||
use Froxlor\Froxlor;
|
||||
use Froxlor\Settings;
|
||||
@@ -61,6 +62,60 @@ class CliCommand extends Command
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
protected function getUserByName(?string $loginname, bool $deactivated_check = true): array
|
||||
{
|
||||
if (empty($loginname)) {
|
||||
throw new Exception("Empty username");
|
||||
}
|
||||
|
||||
$stmt = Database::prepare("
|
||||
SELECT `loginname` AS `customer`
|
||||
FROM `" . TABLE_PANEL_CUSTOMERS . "`
|
||||
WHERE `loginname`= :loginname
|
||||
");
|
||||
Database::pexecute($stmt, [
|
||||
"loginname" => $loginname
|
||||
]);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($row && $row['customer'] == $loginname) {
|
||||
$table = "`" . TABLE_PANEL_CUSTOMERS . "`";
|
||||
$adminsession = '0';
|
||||
} else {
|
||||
$stmt = Database::prepare("
|
||||
SELECT `loginname` AS `admin` FROM `" . TABLE_PANEL_ADMINS . "`
|
||||
WHERE `loginname`= :loginname
|
||||
");
|
||||
Database::pexecute($stmt, [
|
||||
"loginname" => $loginname
|
||||
]);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($row && $row['admin'] == $loginname) {
|
||||
$table = "`" . TABLE_PANEL_ADMINS . "`";
|
||||
$adminsession = '1';
|
||||
} else {
|
||||
throw new Exception("Unknown user '" . $loginname . "'");
|
||||
}
|
||||
}
|
||||
|
||||
$userinfo_stmt = Database::prepare("
|
||||
SELECT * FROM $table
|
||||
WHERE `loginname`= :loginname
|
||||
");
|
||||
Database::pexecute($userinfo_stmt, [
|
||||
"loginname" => $loginname
|
||||
]);
|
||||
$userinfo = $userinfo_stmt->fetch(PDO::FETCH_ASSOC);
|
||||
$userinfo['adminsession'] = $adminsession;
|
||||
|
||||
if ($deactivated_check && $userinfo['deactivated']) {
|
||||
throw new Exception("User '" . $loginname . "' is currently deactivated");
|
||||
}
|
||||
|
||||
return $userinfo;
|
||||
}
|
||||
|
||||
private function runUpdate(OutputInterface $output): int
|
||||
{
|
||||
$output->writeln('<comment>Automatic update is activated and we are going to proceed without any notices</>');
|
||||
|
||||
@@ -126,57 +126,4 @@ final class RunApiCommand extends CliCommand
|
||||
return ['class' => $command[0], 'function' => $command[1]];
|
||||
}
|
||||
|
||||
private function getUserByName(?string $loginname): array
|
||||
{
|
||||
if (empty($loginname)) {
|
||||
throw new Exception("Empty username");
|
||||
}
|
||||
|
||||
$stmt = Database::prepare("
|
||||
SELECT `loginname` AS `customer`
|
||||
FROM `" . TABLE_PANEL_CUSTOMERS . "`
|
||||
WHERE `loginname`= :loginname
|
||||
");
|
||||
Database::pexecute($stmt, [
|
||||
"loginname" => $loginname
|
||||
]);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($row && $row['customer'] == $loginname) {
|
||||
$table = "`" . TABLE_PANEL_CUSTOMERS . "`";
|
||||
$adminsession = '0';
|
||||
} else {
|
||||
$stmt = Database::prepare("
|
||||
SELECT `loginname` AS `admin` FROM `" . TABLE_PANEL_ADMINS . "`
|
||||
WHERE `loginname`= :loginname
|
||||
");
|
||||
Database::pexecute($stmt, [
|
||||
"loginname" => $loginname
|
||||
]);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($row && $row['admin'] == $loginname) {
|
||||
$table = "`" . TABLE_PANEL_ADMINS . "`";
|
||||
$adminsession = '1';
|
||||
} else {
|
||||
throw new Exception("Unknown user '" . $loginname . "'");
|
||||
}
|
||||
}
|
||||
|
||||
$userinfo_stmt = Database::prepare("
|
||||
SELECT * FROM $table
|
||||
WHERE `loginname`= :loginname
|
||||
");
|
||||
Database::pexecute($userinfo_stmt, [
|
||||
"loginname" => $loginname
|
||||
]);
|
||||
$userinfo = $userinfo_stmt->fetch(PDO::FETCH_ASSOC);
|
||||
$userinfo['adminsession'] = $adminsession;
|
||||
|
||||
if ($userinfo['deactivated']) {
|
||||
throw new Exception("User '" . $loginname . "' is currently deactivated");
|
||||
}
|
||||
|
||||
return $userinfo;
|
||||
}
|
||||
}
|
||||
|
||||
135
lib/Froxlor/Cli/UserCommand.php
Normal file
135
lib/Froxlor/Cli/UserCommand.php
Normal file
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Froxlor project.
|
||||
* Copyright (c) 2010 the Froxlor Team (see authors).
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you can also view it online at
|
||||
* https://files.froxlor.org/misc/COPYING.txt
|
||||
*
|
||||
* @copyright the authors
|
||||
* @author Froxlor team <team@froxlor.org>
|
||||
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
|
||||
*/
|
||||
|
||||
namespace Froxlor\Cli;
|
||||
|
||||
use Exception;
|
||||
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\Api\Commands\Admins;
|
||||
use Froxlor\Api\Commands\Customers;
|
||||
use Froxlor\System\Crypt;
|
||||
use Froxlor\Froxlor;
|
||||
|
||||
final class UserCommand extends CliCommand
|
||||
{
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('froxlor:user');
|
||||
$this->setDescription('Various user actions');
|
||||
$this->addArgument('user', InputArgument::REQUIRED, 'Loginname of the target user')
|
||||
->addArgument('admin', InputArgument::OPTIONAL, 'Loginname of the executing admin/reseller user', 'admin');
|
||||
$this->addOption('unlock', 'u', InputOption::VALUE_NONE, 'Unock user after too many failed login attempts')
|
||||
->addOption('change-passwd', 'p', InputOption::VALUE_NONE, 'Set new password for given user')
|
||||
->addOption('show-info', 's', InputOption::VALUE_NONE, 'Output information details of given user');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$result = self::SUCCESS;
|
||||
|
||||
$result = $this->validateRequirements($input, $output);
|
||||
|
||||
require Froxlor::getInstallDir() . '/lib/functions.php';
|
||||
|
||||
// set error-handler
|
||||
@set_error_handler([
|
||||
'\\Froxlor\\Api\\Api',
|
||||
'phpErrHandler'
|
||||
]);
|
||||
|
||||
if ($result == self::SUCCESS) {
|
||||
try {
|
||||
$adminname = $input->getArgument('admin');
|
||||
$admininfo = $this->getUserByName($adminname);
|
||||
$loginname = $input->getArgument('user');
|
||||
$userinfo = $this->getUserByName($loginname, false);
|
||||
|
||||
$do_unlock = $input->getOption('unlock');
|
||||
$do_passwd = $input->getOption('change-passwd');
|
||||
$do_show = $input->getOption('show-info');
|
||||
|
||||
if ($do_unlock === false && $do_passwd === false && $do_show === false) {
|
||||
$output->writeln('<error>No option given, nothing to do.</>');
|
||||
$result = self::INVALID;
|
||||
}
|
||||
|
||||
if ($do_unlock !== false) {
|
||||
// unlock given user
|
||||
if ((int)$userinfo['adminsession'] == 1) {
|
||||
Admins::getLocal($admininfo, ['loginname' => $loginname])->unlock();
|
||||
} else {
|
||||
Customers::getLocal($admininfo, ['loginname' => $loginname])->unlock();
|
||||
}
|
||||
$output->writeln('<info>User ' . $loginname . ' unlocked successfully</>');
|
||||
$result = self::SUCCESS;
|
||||
}
|
||||
if ($result == self::SUCCESS && $do_passwd !== false) {
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
$passwd = $io->askHidden("Enter new password", function ($value) {
|
||||
if (empty($value)) {
|
||||
throw new \RuntimeException('You must enter a value.');
|
||||
}
|
||||
$value = Crypt::validatePassword($value, 'new password');
|
||||
return $value;
|
||||
});
|
||||
$passwd2 = $io->askHidden("Confirm new password", function ($value) use ($passwd) {
|
||||
if (empty($value)) {
|
||||
throw new \RuntimeException('You must enter a value.');
|
||||
} elseif ($value != $passwd) {
|
||||
throw new \RuntimeException('Passwords do not match');
|
||||
}
|
||||
return $value;
|
||||
});
|
||||
if ((int)$userinfo['adminsession'] == 1) {
|
||||
Admins::getLocal($admininfo, ['id' => $userinfo['adminid'], 'admin_password' => $passwd])->update();
|
||||
} else {
|
||||
Customers::getLocal($admininfo, ['id' => $userinfo['customerid'], 'new_customer_password' => $passwd])->update();
|
||||
}
|
||||
$output->writeln('<info>Changed password for ' . $loginname . '</>');
|
||||
$result = self::SUCCESS;
|
||||
}
|
||||
if ($result == self::SUCCESS && $do_show !== false) {
|
||||
$userinfo['password'] = '[hidden]';
|
||||
$userinfo['data_2fa'] = '[hidden]';
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
$io->horizontalTable(
|
||||
array_keys($userinfo),
|
||||
[array_values($userinfo)]
|
||||
);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$output->writeln('<error>' . $e->getMessage() . '</>');
|
||||
$result = self::FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user