* @author Daniel Kesselberg * @author Joas Schilling * @author Robin Appelman * @author Roeland Jago Douma * * @license AGPL-3.0 * * This code is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. * * 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License, version 3, * along with this program. If not, see * */ namespace OCA\Files_External\Command; use OC\Core\Command\Base; use OC\User\NoUserException; use OCA\Files_External\Lib\StorageConfig; use OCA\Files_External\Service\GlobalStoragesService; use OCA\Files_External\Service\StoragesService; use OCA\Files_External\Service\UserStoragesService; use OCP\IUserManager; use OCP\IUserSession; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; class ListCommand extends Base { public const ALL = -1; public function __construct( protected GlobalStoragesService $globalService, protected UserStoragesService $userService, protected IUserSession $userSession, protected IUserManager $userManager, ) { parent::__construct(); } protected function configure(): void { $this ->setName('files_external:list') ->setDescription('List configured admin or personal mounts') ->addArgument( 'user_id', InputArgument::OPTIONAL, 'user id to list the personal mounts for, if no user is provided admin mounts will be listed' )->addOption( 'show-password', '', InputOption::VALUE_NONE, 'show passwords and secrets' )->addOption( 'full', null, InputOption::VALUE_NONE, 'don\'t truncate long values in table output' )->addOption( 'all', 'a', InputOption::VALUE_NONE, 'show both system wide mounts and all personal mounts' ); parent::configure(); } protected function execute(InputInterface $input, OutputInterface $output): int { /** @var StorageConfig[] $mounts */ if ($input->getOption('all')) { $mounts = $this->globalService->getStorageForAllUsers(); $userId = self::ALL; } else { $userId = (string)$input->getArgument('user_id'); $storageService = $this->getStorageService($userId); $mounts = $storageService->getAllStorages(); } $this->listMounts($userId, $mounts, $input, $output); return self::SUCCESS; } /** * @param ?string|ListCommand::ALL $userId * @param StorageConfig[] $mounts */ public function listMounts($userId, array $mounts, InputInterface $input, OutputInterface $output): void { $outputType = $input->getOption('output'); if (count($mounts) === 0) { if ($outputType === self::OUTPUT_FORMAT_JSON || $outputType === self::OUTPUT_FORMAT_JSON_PRETTY) { $output->writeln('[]'); } else { if ($userId === self::ALL) { $output->writeln("No mounts configured"); } elseif ($userId) { $output->writeln("No mounts configured by $userId"); } else { $output->writeln("No admin mounts configured"); } } return; } $headers = ['Mount ID', 'Mount Point', 'Storage', 'Authentication Type', 'Configuration', 'Options']; if (!$userId || $userId === self::ALL) { $headers[] = 'Applicable Users'; $headers[] = 'Applicable Groups'; } if ($userId === self::ALL) { $headers[] = 'Type'; } if (!$input->getOption('show-password')) { $hideKeys = ['key', 'bucket', 'secret', 'password', 'refresh_token', 'token', 'client_secret', 'public_key', 'private_key']; foreach ($mounts as $mount) { $config = $mount->getBackendOptions(); foreach ($config as $key => $value) { if (in_array($key, $hideKeys)) { $mount->setBackendOption($key, '***REMOVED SENSITIVE VALUE***'); } } } } if ($outputType === self::OUTPUT_FORMAT_JSON || $outputType === self::OUTPUT_FORMAT_JSON_PRETTY) { $keys = array_map(function ($header) { return strtolower(str_replace(' ', '_', $header)); }, $headers); $pairs = array_map(function (StorageConfig $config) use ($keys, $userId) { $values = [ $config->getId(), $config->getMountPoint(), $config->getBackend()->getStorageClass(), $config->getAuthMechanism()->getIdentifier(), $config->getBackendOptions(), $config->getMountOptions() ]; if (!$userId || $userId === self::ALL) { $values[] = $config->getApplicableUsers(); $values[] = $config->getApplicableGroups(); } if ($userId === self::ALL) { $values[] = $config->getType() === StorageConfig::MOUNT_TYPE_ADMIN ? 'admin' : 'personal'; } return array_combine($keys, $values); }, $mounts); if ($outputType === self::OUTPUT_FORMAT_JSON) { $output->writeln(json_encode(array_values($pairs))); } else { $output->writeln(json_encode(array_values($pairs), JSON_PRETTY_PRINT)); } } else { $full = $input->getOption('full'); $defaultMountOptions = [ 'encrypt' => true, 'previews' => true, 'filesystem_check_changes' => 1, 'enable_sharing' => false, 'encoding_compatibility' => false, 'readonly' => false, ]; $rows = array_map(function (StorageConfig $config) use ($userId, $defaultMountOptions, $full) { $storageConfig = $config->getBackendOptions(); $keys = array_keys($storageConfig); $values = array_values($storageConfig); if (!$full) { $values = array_map(function ($value) { if (is_string($value) && strlen($value) > 32) { return substr($value, 0, 6) . '...' . substr($value, -6, 6); } else { return $value; } }, $values); } $configStrings = array_map(function ($key, $value) { return $key . ': ' . json_encode($value); }, $keys, $values); $configString = implode(', ', $configStrings); $mountOptions = $config->getMountOptions(); // hide defaults foreach ($mountOptions as $key => $value) { if ($value === $defaultMountOptions[$key]) { unset($mountOptions[$key]); } } $keys = array_keys($mountOptions); $values = array_values($mountOptions); $optionsStrings = array_map(function ($key, $value) { return $key . ': ' . json_encode($value); }, $keys, $values); $optionsString = implode(', ', $optionsStrings); $values = [ $config->getId(), $config->getMountPoint(), $config->getBackend()->getText(), $config->getAuthMechanism()->getText(), $configString, $optionsString ]; if (!$userId || $userId === self::ALL) { $applicableUsers = implode(', ', $config->getApplicableUsers()); $applicableGroups = implode(', ', $config->getApplicableGroups()); if ($applicableUsers === '' && $applicableGroups === '') { $applicableUsers = 'All'; } $values[] = $applicableUsers; $values[] = $applicableGroups; } if ($userId === self::ALL) { $values[] = $config->getType() === StorageConfig::MOUNT_TYPE_ADMIN ? 'Admin' : 'Personal'; } return $values; }, $mounts); $table = new Table($output); $table->setHeaders($headers); $table->setRows($rows); $table->render(); } } protected function getStorageService(string $userId): StoragesService { if (empty($userId)) { return $this->globalService; } $user = $this->userManager->get($userId); if (is_null($user)) { throw new NoUserException("user $userId not found"); } $this->userSession->setUser($user); return $this->userService; } }