You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

223 lines
6.7 KiB

  1. <?php
  2. /**
  3. * @author Robin Appelman <icewind@owncloud.com>
  4. *
  5. * @copyright Copyright (c) 2016, ownCloud, Inc.
  6. * @license AGPL-3.0
  7. *
  8. * This code is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU Affero General Public License, version 3,
  10. * as published by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Affero General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Affero General Public License, version 3,
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>
  19. *
  20. */
  21. namespace OCA\Files_External\Command;
  22. use OC\Core\Command\Base;
  23. use OC\User\NoUserException;
  24. use OCA\Files_external\Lib\StorageConfig;
  25. use OCA\Files_External\Service\BackendService;
  26. use OCA\Files_External\Service\GlobalStoragesService;
  27. use OCA\Files_External\Service\ImportLegacyStoragesService;
  28. use OCA\Files_External\Service\UserStoragesService;
  29. use OCP\IUserManager;
  30. use OCP\IUserSession;
  31. use Symfony\Component\Console\Input\ArrayInput;
  32. use Symfony\Component\Console\Input\InputArgument;
  33. use Symfony\Component\Console\Input\InputInterface;
  34. use Symfony\Component\Console\Input\InputOption;
  35. use Symfony\Component\Console\Output\OutputInterface;
  36. class Import extends Base {
  37. /**
  38. * @var GlobalStoragesService
  39. */
  40. private $globalService;
  41. /**
  42. * @var UserStoragesService
  43. */
  44. private $userService;
  45. /**
  46. * @var IUserSession
  47. */
  48. private $userSession;
  49. /**
  50. * @var IUserManager
  51. */
  52. private $userManager;
  53. /** @var ImportLegacyStoragesService */
  54. private $importLegacyStorageService;
  55. /** @var BackendService */
  56. private $backendService;
  57. function __construct(GlobalStoragesService $globalService,
  58. UserStoragesService $userService,
  59. IUserSession $userSession,
  60. IUserManager $userManager,
  61. ImportLegacyStoragesService $importLegacyStorageService,
  62. BackendService $backendService
  63. ) {
  64. parent::__construct();
  65. $this->globalService = $globalService;
  66. $this->userService = $userService;
  67. $this->userSession = $userSession;
  68. $this->userManager = $userManager;
  69. $this->importLegacyStorageService = $importLegacyStorageService;
  70. $this->backendService = $backendService;
  71. }
  72. protected function configure() {
  73. $this
  74. ->setName('files_external:import')
  75. ->setDescription('Import mount configurations')
  76. ->addOption(
  77. 'user',
  78. null,
  79. InputOption::VALUE_OPTIONAL,
  80. 'user to add the mount configurations for, if not set the mount will be added as system mount'
  81. )
  82. ->addArgument(
  83. 'path',
  84. InputArgument::REQUIRED,
  85. 'path to a json file containing the mounts to import, use "-" to read from stdin'
  86. )
  87. ->addOption(
  88. 'dry',
  89. null,
  90. InputOption::VALUE_NONE,
  91. 'Don\'t save the imported mounts, only list the new mounts'
  92. );
  93. parent::configure();
  94. }
  95. protected function execute(InputInterface $input, OutputInterface $output) {
  96. $user = $input->getOption('user');
  97. $path = $input->getArgument('path');
  98. if ($path === '-') {
  99. $json = file_get_contents('php://stdin');
  100. } else {
  101. if (!file_exists($path)) {
  102. $output->writeln('<error>File not found: ' . $path . '</error>');
  103. return 1;
  104. }
  105. $json = file_get_contents($path);
  106. }
  107. if (!is_string($json) || strlen($json) < 2) {
  108. $output->writeln('<error>Error while reading json</error>');
  109. return 1;
  110. }
  111. $data = json_decode($json, true);
  112. if (!is_array($data)) {
  113. $output->writeln('<error>Error while parsing json</error>');
  114. return 1;
  115. }
  116. $isLegacy = isset($data['user']) || isset($data['group']);
  117. if ($isLegacy) {
  118. $this->importLegacyStorageService->setData($data);
  119. $mounts = $this->importLegacyStorageService->getAllStorages();
  120. foreach ($mounts as $mount) {
  121. if ($mount->getBackendOption('password') === false) {
  122. $output->writeln('<error>Failed to decrypt password</error>');
  123. return 1;
  124. }
  125. }
  126. } else {
  127. if (!isset($data[0])) { //normalize to an array of mounts
  128. $data = [$data];
  129. }
  130. $mounts = array_map([$this, 'parseData'], $data);
  131. }
  132. if ($user) {
  133. // ensure applicables are correct for personal mounts
  134. foreach ($mounts as $mount) {
  135. $mount->setApplicableGroups([]);
  136. $mount->setApplicableUsers([$user]);
  137. }
  138. }
  139. $storageService = $this->getStorageService($user);
  140. $existingMounts = $storageService->getAllStorages();
  141. foreach ($mounts as $mount) {
  142. foreach ($existingMounts as $existingMount) {
  143. if (
  144. $existingMount->getMountPoint() === $mount->getMountPoint() &&
  145. $existingMount->getApplicableGroups() === $mount->getApplicableGroups() &&
  146. $existingMount->getApplicableUsers() == $mount->getApplicableUsers() &&
  147. $existingMount->getBackendOptions() == $mount->getBackendOptions()
  148. ) {
  149. $output->writeln("<error>Duplicate mount (" . $mount->getMountPoint() . ")</error>");
  150. return 1;
  151. }
  152. }
  153. }
  154. if ($input->getOption('dry')) {
  155. if (count($mounts) === 0) {
  156. $output->writeln('<error>No mounts to be imported</error>');
  157. return 1;
  158. }
  159. $listCommand = new ListCommand($this->globalService, $this->userService, $this->userSession, $this->userManager);
  160. $listInput = new ArrayInput([], $listCommand->getDefinition());
  161. $listInput->setOption('output', $input->getOption('output'));
  162. $listInput->setOption('show-password', true);
  163. $listCommand->listMounts($user, $mounts, $listInput, $output);
  164. } else {
  165. foreach ($mounts as $mount) {
  166. $storageService->addStorage($mount);
  167. }
  168. }
  169. return 0;
  170. }
  171. private function parseData(array $data) {
  172. $mount = new StorageConfig($data['mount_id']);
  173. $mount->setMountPoint($data['mount_point']);
  174. $mount->setBackend($this->getBackendByClass($data['storage']));
  175. $authBackend = $this->backendService->getAuthMechanism($data['authentication_type']);
  176. $mount->setAuthMechanism($authBackend);
  177. $mount->setBackendOptions($data['configuration']);
  178. $mount->setMountOptions($data['options']);
  179. $mount->setApplicableUsers(isset($data['applicable_users']) ? $data['applicable_users'] : []);
  180. $mount->setApplicableGroups(isset($data['applicable_groups']) ? $data['applicable_groups'] : []);
  181. return $mount;
  182. }
  183. private function getBackendByClass($className) {
  184. $backends = $this->backendService->getBackends();
  185. foreach ($backends as $backend) {
  186. if ($backend->getStorageClass() === $className) {
  187. return $backend;
  188. }
  189. }
  190. }
  191. protected function getStorageService($userId) {
  192. if (!empty($userId)) {
  193. $user = $this->userManager->get($userId);
  194. if (is_null($user)) {
  195. throw new NoUserException("user $userId not found");
  196. }
  197. $this->userSession->setUser($user);
  198. return $this->userService;
  199. } else {
  200. return $this->globalService;
  201. }
  202. }
  203. }