| Current Path : /proc/3751963/cwd/public_html/pano.4uweb.ca/src/CliCommand/ |
| Current File : //proc/3751963/cwd/public_html/pano.4uweb.ca/src/CliCommand/UserAdd.php |
<?php
/**
* @package panopticon
* @copyright Copyright (c)2023-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license https://www.gnu.org/licenses/agpl-3.0.txt GNU Affero General Public License, version 3 or later
*/
namespace Akeeba\Panopticon\CliCommand;
defined('AKEEBA') || die;
use Akeeba\Panopticon\Application\UserAuthenticationPassword;
use Akeeba\Panopticon\Application\UserPrivileges;
use Akeeba\Panopticon\CliCommand\Attribute\ConfigAssertion;
use Akeeba\Panopticon\Factory;
use Complexify\Complexify;
use RuntimeException;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
#[AsCommand(
name: 'user:add',
description: 'Creates or overwrites a user',
hidden: false,
)]
#[ConfigAssertion(true)]
class UserAdd extends AbstractCommand
{
protected function interact(InputInterface $input, OutputInterface $output)
{
$username = $input->getOption('username');
if (empty($username))
{
$username = $this->ioStyle->ask(
'Please enter the username',
null,
function ($value) {
if (empty($value) || preg_match('#^[a-zA-Z0-9_\-.\$!@\#%^&*()\[\]{}:;\"\',/<>?|\\\\]{1,255}$#i', $value) <= 0)
{
throw new RuntimeException('The username must be 1 to 255 characters long and consist of a-z, A-Z, 0-9 and the characters !@#$%^&*()_+[]{};:\'"\\|,<.>/?');
}
return $value;
}
);
$input->setOption('username', $username);
}
$password = $input->getOption('password');
if (empty($password))
{
$pass1 = $this->ioStyle->askHidden(
'Please enter the password (12+ characters)',
function ($value) {
if (empty($value))
{
throw new RuntimeException('The password cannot be empty');
}
$result = $this->getComplexify()->evaluateSecurity($value);
if (!$result->valid)
{
if (in_array('banned', $result->errors))
{
throw new RuntimeException('The password is in a list of known bad passwords.');
}
elseif (in_array('tooshort', $result->errors))
{
throw new RuntimeException('The password is too short.');
}
throw new RuntimeException('The password is too easy to crack.');
}
$this->ioStyle->info(sprintf('Password quality: %0.0f%%', $result->complexity));
return $value;
}
);
// Just using the validator is enough to guarantee that the passwords match
$pass2 = $this->ioStyle->askHidden(
'Please repeat the password',
function ($value) use ($pass1) {
if ($value !== $pass1)
{
throw new RuntimeException('The passwords must match');
}
return $value;
}
);
$input->setOption('password', $pass1);
}
$email = $input->getOption('email');
if (empty($email))
{
$email = $this->ioStyle->ask(
'Please enter the email address',
null,
function ($value) {
if (empty($value))
{
throw new RuntimeException('The email address cannot be empty.');
}
if (!filter_var($value, FILTER_VALIDATE_EMAIL))
{
throw new RuntimeException('Invalid email address.');
}
return $value;
}
);
$input->setOption('email', $email);
}
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$username = $input->getOption('username');
$password = $input->getOption('password');
$email = $input->getOption('email');
$name = $input->getOption('name') ?? $username;
$overwrite = (bool) $input->getOption('overwrite') ?? false;
$container = Factory::getContainer();
$manager = $container->userManager;
$manager->registerPrivilegePlugin('panopticon', UserPrivileges::class);
$manager->registerAuthenticationPlugin('password', UserAuthenticationPassword::class);
$user = $manager->getUserByUsername($username);
if (!empty($user) && !$overwrite)
{
$this->ioStyle->error(
sprintf('User %s already exists.', $username)
);
return Command::FAILURE;
}
elseif (!empty($user))
{
$this->ioStyle->warning(
sprintf('Modifying existing user %s.', $username)
);
}
else
{
$this->ioStyle->info(
sprintf('Creating new user %s.', $username)
);
}
$user = $user ?: $manager->getUser(0);
$data = [
'username' => $username,
'name' => $name,
'email' => $email,
];
$user->bind($data);
$user->setPassword($password);
$privileges = $input->getOption('permission');
$privileges = $privileges ?: [];
$privileges = is_array($privileges) ? $privileges : array($privileges);
foreach ($privileges as $privilege)
{
$user->setPrivilege($privilege, true);
}
$manager->saveUser($user);
$this->ioStyle->success(
sprintf('Successfully saved user %s.', $username)
);
return Command::SUCCESS;
}
protected function configure()
{
$this
->addOption('username', null, InputOption::VALUE_REQUIRED, 'Username')
->addOption('password', null, InputOption::VALUE_REQUIRED, 'Password')
->addOption('email', null, InputOption::VALUE_REQUIRED, 'Email address')
->addOption('name', null, InputOption::VALUE_OPTIONAL, 'Full name')
->addOption('overwrite', null, InputOption::VALUE_NEGATABLE, 'Overwrite an existing user?', false)
->addOption('permission', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Which permission(s) to add to the user account')
;
}
private function getComplexify(): Complexify
{
return new Complexify([
'minimumChars' => 12,
'encoding' => 'UTF-8',
]);
}
}