diff options
Diffstat (limited to 'core/Command/TwoFactorAuth')
-rw-r--r-- | core/Command/TwoFactorAuth/Base.php | 47 | ||||
-rw-r--r-- | core/Command/TwoFactorAuth/Cleanup.php | 44 | ||||
-rw-r--r-- | core/Command/TwoFactorAuth/Disable.php | 52 | ||||
-rw-r--r-- | core/Command/TwoFactorAuth/Enable.php | 52 | ||||
-rw-r--r-- | core/Command/TwoFactorAuth/Enforce.php | 88 | ||||
-rw-r--r-- | core/Command/TwoFactorAuth/State.php | 88 |
6 files changed, 371 insertions, 0 deletions
diff --git a/core/Command/TwoFactorAuth/Base.php b/core/Command/TwoFactorAuth/Base.php new file mode 100644 index 00000000000..034ea36afca --- /dev/null +++ b/core/Command/TwoFactorAuth/Base.php @@ -0,0 +1,47 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OC\Core\Command\TwoFactorAuth; + +use OCP\IUser; +use OCP\IUserManager; +use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext; + +class Base extends \OC\Core\Command\Base { + public function __construct( + ?string $name, + protected IUserManager $userManager, + ) { + parent::__construct($name); + } + + /** + * Return possible values for the named option + * + * @param string $optionName + * @param CompletionContext $context + * @return string[] + */ + public function completeOptionValues($optionName, CompletionContext $context) { + return []; + } + + /** + * Return possible values for the named argument + * + * @param string $argumentName + * @param CompletionContext $context + * @return string[] + */ + public function completeArgumentValues($argumentName, CompletionContext $context) { + if ($argumentName === 'uid') { + return array_map(function (IUser $user) { + return $user->getUID(); + }, $this->userManager->search($context->getCurrentWord(), 100)); + } + return []; + } +} diff --git a/core/Command/TwoFactorAuth/Cleanup.php b/core/Command/TwoFactorAuth/Cleanup.php new file mode 100644 index 00000000000..f8f116af3fd --- /dev/null +++ b/core/Command/TwoFactorAuth/Cleanup.php @@ -0,0 +1,44 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OC\Core\Command\TwoFactorAuth; + +use OCP\Authentication\TwoFactorAuth\IRegistry; +use OCP\IUserManager; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class Cleanup extends Base { + public function __construct( + private IRegistry $registry, + IUserManager $userManager, + ) { + parent::__construct( + null, + $userManager, + ); + } + + protected function configure() { + parent::configure(); + + $this->setName('twofactorauth:cleanup'); + $this->setDescription('Clean up the two-factor user-provider association of an uninstalled/removed provider'); + $this->addArgument('provider-id', InputArgument::REQUIRED); + } + + protected function execute(InputInterface $input, OutputInterface $output): int { + $providerId = $input->getArgument('provider-id'); + + $this->registry->cleanUp($providerId); + + $output->writeln("<info>All user-provider associations for provider <options=bold>$providerId</> have been removed.</info>"); + return 0; + } +} diff --git a/core/Command/TwoFactorAuth/Disable.php b/core/Command/TwoFactorAuth/Disable.php new file mode 100644 index 00000000000..c60c1245735 --- /dev/null +++ b/core/Command/TwoFactorAuth/Disable.php @@ -0,0 +1,52 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only + */ +namespace OC\Core\Command\TwoFactorAuth; + +use OC\Authentication\TwoFactorAuth\ProviderManager; +use OCP\IUserManager; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class Disable extends Base { + public function __construct( + private ProviderManager $manager, + IUserManager $userManager, + ) { + parent::__construct( + 'twofactorauth:disable', + $userManager, + ); + } + + protected function configure() { + parent::configure(); + + $this->setName('twofactorauth:disable'); + $this->setDescription('Disable two-factor authentication for a user'); + $this->addArgument('uid', InputArgument::REQUIRED); + $this->addArgument('provider_id', InputArgument::REQUIRED); + } + + protected function execute(InputInterface $input, OutputInterface $output): int { + $uid = $input->getArgument('uid'); + $providerId = $input->getArgument('provider_id'); + $user = $this->userManager->get($uid); + if (is_null($user)) { + $output->writeln('<error>Invalid UID</error>'); + return 1; + } + if ($this->manager->tryDisableProviderFor($providerId, $user)) { + $output->writeln("Two-factor provider <options=bold>$providerId</> disabled for user <options=bold>$uid</>."); + return 0; + } else { + $output->writeln('<error>The provider does not support this operation.</error>'); + return 2; + } + } +} diff --git a/core/Command/TwoFactorAuth/Enable.php b/core/Command/TwoFactorAuth/Enable.php new file mode 100644 index 00000000000..215cb31397e --- /dev/null +++ b/core/Command/TwoFactorAuth/Enable.php @@ -0,0 +1,52 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only + */ +namespace OC\Core\Command\TwoFactorAuth; + +use OC\Authentication\TwoFactorAuth\ProviderManager; +use OCP\IUserManager; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class Enable extends Base { + public function __construct( + private ProviderManager $manager, + IUserManager $userManager, + ) { + parent::__construct( + 'twofactorauth:enable', + $userManager, + ); + } + + protected function configure() { + parent::configure(); + + $this->setName('twofactorauth:enable'); + $this->setDescription('Enable two-factor authentication for a user'); + $this->addArgument('uid', InputArgument::REQUIRED); + $this->addArgument('provider_id', InputArgument::REQUIRED); + } + + protected function execute(InputInterface $input, OutputInterface $output): int { + $uid = $input->getArgument('uid'); + $providerId = $input->getArgument('provider_id'); + $user = $this->userManager->get($uid); + if (is_null($user)) { + $output->writeln('<error>Invalid UID</error>'); + return 1; + } + if ($this->manager->tryEnableProviderFor($providerId, $user)) { + $output->writeln("Two-factor provider <options=bold>$providerId</> enabled for user <options=bold>$uid</>."); + return 0; + } else { + $output->writeln('<error>The provider does not support this operation.</error>'); + return 2; + } + } +} diff --git a/core/Command/TwoFactorAuth/Enforce.php b/core/Command/TwoFactorAuth/Enforce.php new file mode 100644 index 00000000000..3315f045bc8 --- /dev/null +++ b/core/Command/TwoFactorAuth/Enforce.php @@ -0,0 +1,88 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OC\Core\Command\TwoFactorAuth; + +use OC\Authentication\TwoFactorAuth\EnforcementState; +use OC\Authentication\TwoFactorAuth\MandatoryTwoFactor; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use function implode; + +class Enforce extends Command { + public function __construct( + private MandatoryTwoFactor $mandatoryTwoFactor, + ) { + parent::__construct(); + } + + protected function configure() { + $this->setName('twofactorauth:enforce'); + $this->setDescription('Enabled/disable enforced two-factor authentication'); + $this->addOption( + 'on', + null, + InputOption::VALUE_NONE, + 'enforce two-factor authentication' + ); + $this->addOption( + 'off', + null, + InputOption::VALUE_NONE, + 'don\'t enforce two-factor authenticaton' + ); + $this->addOption( + 'group', + null, + InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, + 'enforce only for the given group(s)' + ); + $this->addOption( + 'exclude', + null, + InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, + 'exclude mandatory two-factor auth for the given group(s)' + ); + } + + protected function execute(InputInterface $input, OutputInterface $output): int { + if ($input->getOption('on')) { + $enforcedGroups = $input->getOption('group'); + $excludedGroups = $input->getOption('exclude'); + $this->mandatoryTwoFactor->setState(new EnforcementState(true, $enforcedGroups, $excludedGroups)); + } elseif ($input->getOption('off')) { + $this->mandatoryTwoFactor->setState(new EnforcementState(false)); + } + + $state = $this->mandatoryTwoFactor->getState(); + if ($state->isEnforced()) { + $this->writeEnforced($output, $state); + } else { + $this->writeNotEnforced($output); + } + return 0; + } + + protected function writeEnforced(OutputInterface $output, EnforcementState $state) { + if (empty($state->getEnforcedGroups())) { + $message = 'Two-factor authentication is enforced for all users'; + } else { + $message = 'Two-factor authentication is enforced for members of the group(s) ' . implode(', ', $state->getEnforcedGroups()); + } + if (!empty($state->getExcludedGroups())) { + $message .= ', except members of ' . implode(', ', $state->getExcludedGroups()); + } + $output->writeln($message); + } + + protected function writeNotEnforced(OutputInterface $output) { + $output->writeln('Two-factor authentication is not enforced'); + } +} diff --git a/core/Command/TwoFactorAuth/State.php b/core/Command/TwoFactorAuth/State.php new file mode 100644 index 00000000000..ab2e8f2aecf --- /dev/null +++ b/core/Command/TwoFactorAuth/State.php @@ -0,0 +1,88 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OC\Core\Command\TwoFactorAuth; + +use OCP\Authentication\TwoFactorAuth\IRegistry; +use OCP\IUserManager; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class State extends Base { + public function __construct( + private IRegistry $registry, + IUserManager $userManager, + ) { + parent::__construct( + 'twofactorauth:state', + $userManager, + ); + } + + protected function configure() { + parent::configure(); + + $this->setName('twofactorauth:state'); + $this->setDescription('Get the two-factor authentication (2FA) state of a user'); + $this->addArgument('uid', InputArgument::REQUIRED); + } + + protected function execute(InputInterface $input, OutputInterface $output): int { + $uid = $input->getArgument('uid'); + $user = $this->userManager->get($uid); + if (is_null($user)) { + $output->writeln('<error>Invalid UID</error>'); + return 1; + } + + $providerStates = $this->registry->getProviderStates($user); + $filtered = $this->filterEnabledDisabledUnknownProviders($providerStates); + [$enabled, $disabled] = $filtered; + + if (!empty($enabled)) { + $output->writeln("Two-factor authentication is enabled for user $uid"); + } else { + $output->writeln("Two-factor authentication is not enabled for user $uid"); + } + + $output->writeln(''); + $this->printProviders('Enabled providers', $enabled, $output); + $this->printProviders('Disabled providers', $disabled, $output); + + return 0; + } + + private function filterEnabledDisabledUnknownProviders(array $providerStates): array { + $enabled = []; + $disabled = []; + + foreach ($providerStates as $providerId => $isEnabled) { + if ($isEnabled) { + $enabled[] = $providerId; + } else { + $disabled[] = $providerId; + } + } + + return [$enabled, $disabled]; + } + + private function printProviders(string $title, array $providers, + OutputInterface $output) { + if (empty($providers)) { + // Ignore and don't print anything + return; + } + + $output->writeln($title . ':'); + foreach ($providers as $provider) { + $output->writeln('- ' . $provider); + } + } +} |