Completed
Push — master ( 03449d...db6361 )
by Lukas
44s queued 24s
created

ListCommand::execute()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 2
eloc 9
c 1
b 0
f 1
nc 2
nop 2
dl 0
loc 15
rs 9.4285
1
<?php
2
/**
3
 * @author Joas Schilling <[email protected]>
4
 * @author Robin Appelman <[email protected]>
5
 *
6
 * @copyright Copyright (c) 2016, ownCloud, Inc.
7
 * @license AGPL-3.0
8
 *
9
 * This code is free software: you can redistribute it and/or modify
10
 * it under the terms of the GNU Affero General Public License, version 3,
11
 * as published by the Free Software Foundation.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
 * GNU Affero General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Affero General Public License, version 3,
19
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
20
 *
21
 */
22
23
namespace OCA\Files_External\Command;
24
25
use OC\Core\Command\Base;
26
use OC\User\NoUserException;
27
use OCA\Files_External\Lib\StorageConfig;
28
use OCA\Files_External\Service\GlobalStoragesService;
29
use OCA\Files_External\Service\UserStoragesService;
30
use OCP\IUserManager;
31
use OCP\IUserSession;
32
use Symfony\Component\Console\Helper\Table;
33
use Symfony\Component\Console\Input\InputArgument;
34
use Symfony\Component\Console\Input\InputInterface;
35
use Symfony\Component\Console\Input\InputOption;
36
use Symfony\Component\Console\Output\OutputInterface;
37
38
class ListCommand extends Base {
39
	/**
40
	 * @var GlobalStoragesService
41
	 */
42
	protected $globalService;
43
44
	/**
45
	 * @var UserStoragesService
46
	 */
47
	protected $userService;
48
49
	/**
50
	 * @var IUserSession
51
	 */
52
	protected $userSession;
53
54
	/**
55
	 * @var IUserManager
56
	 */
57
	protected $userManager;
58
59
	const ALL = -1;
60
61 View Code Duplication
	function __construct(GlobalStoragesService $globalService, UserStoragesService $userService, IUserSession $userSession, IUserManager $userManager) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
62
		parent::__construct();
63
		$this->globalService = $globalService;
64
		$this->userService = $userService;
65
		$this->userSession = $userSession;
66
		$this->userManager = $userManager;
67
	}
68
69
	protected function configure() {
70
		$this
71
			->setName('files_external:list')
72
			->setDescription('List configured admin or personal mounts')
73
			->addArgument(
74
				'user_id',
75
				InputArgument::OPTIONAL,
76
				'user id to list the personal mounts for, if no user is provided admin mounts will be listed'
77
			)->addOption(
78
				'show-password',
79
				null,
80
				InputOption::VALUE_NONE,
81
				'show passwords and secrets'
82
			)->addOption(
83
				'full',
84
				null,
85
				InputOption::VALUE_NONE,
86
				'don\'t truncate long values in table output'
87
			)->addOption(
88
				'all',
89
				'a',
90
				InputOption::VALUE_NONE,
91
				'show both system wide mounts and all personal mounts'
92
			);
93
		parent::configure();
94
	}
95
96
	protected function execute(InputInterface $input, OutputInterface $output) {
97
		if ($input->getOption('all')) {
98
			/** @var  $mounts StorageConfig[] */
99
			$mounts = $this->globalService->getStorageForAllUsers();
100
			$userId = self::ALL;
101
		} else {
102
			$userId = $input->getArgument('user_id');
103
			$storageService = $this->getStorageService($userId);
104
105
			/** @var  $mounts StorageConfig[] */
106
			$mounts = $storageService->getAllStorages();
107
		}
108
109
		$this->listMounts($userId, $mounts, $input, $output);
110
	}
111
112
	/**
113
	 * @param $userId $userId
0 ignored issues
show
Documentation introduced by
The doc-type $userId could not be parsed: Unknown type name "$userId" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
114
	 * @param StorageConfig[] $mounts
115
	 * @param InputInterface $input
116
	 * @param OutputInterface $output
117
	 */
118
	public function listMounts($userId, array $mounts, InputInterface $input, OutputInterface $output) {
119
		$outputType = $input->getOption('output');
120
		if (count($mounts) === 0) {
121
			if ($outputType === self::OUTPUT_FORMAT_JSON || $outputType === self::OUTPUT_FORMAT_JSON_PRETTY) {
122
				$output->writeln('[]');
123
			} else {
124
				if ($userId === self::ALL) {
125
					$output->writeln("<info>No mounts configured</info>");
126
				} else if ($userId) {
127
					$output->writeln("<info>No mounts configured by $userId</info>");
128
				} else {
129
					$output->writeln("<info>No admin mounts configured</info>");
130
				}
131
			}
132
			return;
133
		}
134
135
		$headers = ['Mount ID', 'Mount Point', 'Storage', 'Authentication Type', 'Configuration', 'Options'];
136
137
		if (!$userId || $userId === self::ALL) {
138
			$headers[] = 'Applicable Users';
139
			$headers[] = 'Applicable Groups';
140
		}
141
		if ($userId === self::ALL) {
142
			$headers[] = 'Type';
143
		}
144
145
		if (!$input->getOption('show-password')) {
146
			$hideKeys = ['password', 'refresh_token', 'token', 'client_secret', 'public_key', 'private_key'];
147
			foreach ($mounts as $mount) {
148
				$config = $mount->getBackendOptions();
149
				foreach ($config as $key => $value) {
150
					if (in_array($key, $hideKeys)) {
151
						$mount->setBackendOption($key, '***');
152
					}
153
				}
154
			}
155
		}
156
157
		if ($outputType === self::OUTPUT_FORMAT_JSON || $outputType === self::OUTPUT_FORMAT_JSON_PRETTY) {
158
			$keys = array_map(function ($header) {
159
				return strtolower(str_replace(' ', '_', $header));
160
			}, $headers);
161
162
			$pairs = array_map(function (StorageConfig $config) use ($keys, $userId) {
163
				$values = [
164
					$config->getId(),
165
					$config->getMountPoint(),
166
					$config->getBackend()->getStorageClass(),
167
					$config->getAuthMechanism()->getIdentifier(),
168
					$config->getBackendOptions(),
169
					$config->getMountOptions()
170
				];
171
				if (!$userId || $userId === self::ALL) {
172
					$values[] = $config->getApplicableUsers();
173
					$values[] = $config->getApplicableGroups();
174
				}
175 View Code Duplication
				if ($userId === self::ALL) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
176
					$values[] = $config->getType() === StorageConfig::MOUNT_TYPE_ADMIN ? 'admin' : 'personal';
177
				}
178
179
				return array_combine($keys, $values);
180
			}, $mounts);
181 View Code Duplication
			if ($outputType === self::OUTPUT_FORMAT_JSON) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
182
				$output->writeln(json_encode(array_values($pairs)));
183
			} else {
184
				$output->writeln(json_encode(array_values($pairs), JSON_PRETTY_PRINT));
185
			}
186
		} else {
187
			$full = $input->getOption('full');
188
			$defaultMountOptions = [
189
				'encrypt' => true,
190
				'previews' => true,
191
				'filesystem_check_changes' => 1,
192
				'enable_sharing' => false,
193
				'encoding_compatibility' => false
194
			];
195
			$rows = array_map(function (StorageConfig $config) use ($userId, $defaultMountOptions, $full) {
196
				$storageConfig = $config->getBackendOptions();
197
				$keys = array_keys($storageConfig);
198
				$values = array_values($storageConfig);
199
200
				if (!$full) {
201
					$values = array_map(function ($value) {
202
						if (is_string($value) && strlen($value) > 32) {
203
							return substr($value, 0, 6) . '...' . substr($value, -6, 6);
204
						} else {
205
							return $value;
206
						}
207
					}, $values);
208
				}
209
210
				$configStrings = array_map(function ($key, $value) {
211
					return $key . ': ' . json_encode($value);
212
				}, $keys, $values);
213
				$configString = implode(', ', $configStrings);
214
215
				$mountOptions = $config->getMountOptions();
216
				// hide defaults
217
				foreach ($mountOptions as $key => $value) {
218
					if ($value === $defaultMountOptions[$key]) {
219
						unset($mountOptions[$key]);
220
					}
221
				}
222
				$keys = array_keys($mountOptions);
223
				$values = array_values($mountOptions);
224
225
				$optionsStrings = array_map(function ($key, $value) {
226
					return $key . ': ' . json_encode($value);
227
				}, $keys, $values);
228
				$optionsString = implode(', ', $optionsStrings);
229
230
				$values = [
231
					$config->getId(),
232
					$config->getMountPoint(),
233
					$config->getBackend()->getText(),
234
					$config->getAuthMechanism()->getText(),
235
					$configString,
236
					$optionsString
237
				];
238
239
				if (!$userId || $userId === self::ALL) {
240
					$applicableUsers = implode(', ', $config->getApplicableUsers());
241
					$applicableGroups = implode(', ', $config->getApplicableGroups());
242
					if ($applicableUsers === '' && $applicableGroups === '') {
243
						$applicableUsers = 'All';
244
					}
245
					$values[] = $applicableUsers;
246
					$values[] = $applicableGroups;
247
				}
248 View Code Duplication
				if ($userId === self::ALL) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
249
					$values[] = $config->getType() === StorageConfig::MOUNT_TYPE_ADMIN ? 'Admin' : 'Personal';
250
				}
251
252
				return $values;
253
			}, $mounts);
254
255
			$table = new Table($output);
256
			$table->setHeaders($headers);
257
			$table->setRows($rows);
258
			$table->render();
259
		}
260
	}
261
262 View Code Duplication
	protected function getStorageService($userId) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
263
		if (!empty($userId)) {
264
			$user = $this->userManager->get($userId);
265
			if (is_null($user)) {
266
				throw new NoUserException("user $userId not found");
267
			}
268
			$this->userSession->setUser($user);
269
			return $this->userService;
270
		} else {
271
			return $this->globalService;
272
		}
273
	}
274
}
275