ProviderFactory.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
  5. * SPDX-License-Identifier: AGPL-3.0-only
  6. */
  7. namespace OC\Share20;
  8. use OC\Share20\Exception\ProviderException;
  9. use OCA\FederatedFileSharing\AddressHandler;
  10. use OCA\FederatedFileSharing\FederatedShareProvider;
  11. use OCA\FederatedFileSharing\Notifications;
  12. use OCA\FederatedFileSharing\TokenHandler;
  13. use OCA\ShareByMail\Settings\SettingsManager;
  14. use OCA\ShareByMail\ShareByMailProvider;
  15. use OCA\Talk\Share\RoomShareProvider;
  16. use OCP\AppFramework\Utility\ITimeFactory;
  17. use OCP\Defaults;
  18. use OCP\EventDispatcher\IEventDispatcher;
  19. use OCP\Federation\ICloudFederationFactory;
  20. use OCP\Files\IRootFolder;
  21. use OCP\Http\Client\IClientService;
  22. use OCP\IServerContainer;
  23. use OCP\L10N\IFactory;
  24. use OCP\Mail\IMailer;
  25. use OCP\Security\IHasher;
  26. use OCP\Security\ISecureRandom;
  27. use OCP\Share\IManager;
  28. use OCP\Share\IProviderFactory;
  29. use OCP\Share\IShare;
  30. use OCP\Share\IShareProvider;
  31. use Psr\Log\LoggerInterface;
  32. /**
  33. * Class ProviderFactory
  34. *
  35. * @package OC\Share20
  36. */
  37. class ProviderFactory implements IProviderFactory {
  38. /** @var IServerContainer */
  39. private $serverContainer;
  40. /** @var DefaultShareProvider */
  41. private $defaultProvider = null;
  42. /** @var FederatedShareProvider */
  43. private $federatedProvider = null;
  44. /** @var ShareByMailProvider */
  45. private $shareByMailProvider;
  46. /** @var \OCA\Circles\ShareByCircleProvider */
  47. private $shareByCircleProvider = null;
  48. /** @var bool */
  49. private $circlesAreNotAvailable = false;
  50. /** @var \OCA\Talk\Share\RoomShareProvider */
  51. private $roomShareProvider = null;
  52. private $registeredShareProviders = [];
  53. private $shareProviders = [];
  54. /**
  55. * IProviderFactory constructor.
  56. *
  57. * @param IServerContainer $serverContainer
  58. */
  59. public function __construct(IServerContainer $serverContainer) {
  60. $this->serverContainer = $serverContainer;
  61. }
  62. public function registerProvider(string $shareProviderClass): void {
  63. $this->registeredShareProviders[] = $shareProviderClass;
  64. }
  65. /**
  66. * Create the default share provider.
  67. *
  68. * @return DefaultShareProvider
  69. */
  70. protected function defaultShareProvider() {
  71. if ($this->defaultProvider === null) {
  72. $this->defaultProvider = new DefaultShareProvider(
  73. $this->serverContainer->getDatabaseConnection(),
  74. $this->serverContainer->getUserManager(),
  75. $this->serverContainer->getGroupManager(),
  76. $this->serverContainer->get(IRootFolder::class),
  77. $this->serverContainer->get(IMailer::class),
  78. $this->serverContainer->query(Defaults::class),
  79. $this->serverContainer->get(IFactory::class),
  80. $this->serverContainer->getURLGenerator(),
  81. $this->serverContainer->query(ITimeFactory::class),
  82. $this->serverContainer->get(LoggerInterface::class),
  83. $this->serverContainer->get(IManager::class),
  84. );
  85. }
  86. return $this->defaultProvider;
  87. }
  88. /**
  89. * Create the federated share provider
  90. *
  91. * @return FederatedShareProvider
  92. */
  93. protected function federatedShareProvider() {
  94. if ($this->federatedProvider === null) {
  95. /*
  96. * Check if the app is enabled
  97. */
  98. $appManager = $this->serverContainer->getAppManager();
  99. if (!$appManager->isEnabledForUser('federatedfilesharing')) {
  100. return null;
  101. }
  102. /*
  103. * TODO: add factory to federated sharing app
  104. */
  105. $l = $this->serverContainer->getL10N('federatedfilesharing');
  106. $addressHandler = new AddressHandler(
  107. $this->serverContainer->getURLGenerator(),
  108. $l,
  109. $this->serverContainer->getCloudIdManager()
  110. );
  111. $notifications = new Notifications(
  112. $addressHandler,
  113. $this->serverContainer->get(IClientService::class),
  114. $this->serverContainer->query(\OCP\OCS\IDiscoveryService::class),
  115. $this->serverContainer->getJobList(),
  116. \OC::$server->getCloudFederationProviderManager(),
  117. \OC::$server->get(ICloudFederationFactory::class),
  118. $this->serverContainer->query(IEventDispatcher::class),
  119. $this->serverContainer->get(LoggerInterface::class),
  120. );
  121. $tokenHandler = new TokenHandler(
  122. $this->serverContainer->get(ISecureRandom::class)
  123. );
  124. $this->federatedProvider = new FederatedShareProvider(
  125. $this->serverContainer->getDatabaseConnection(),
  126. $addressHandler,
  127. $notifications,
  128. $tokenHandler,
  129. $l,
  130. $this->serverContainer->get(IRootFolder::class),
  131. $this->serverContainer->getConfig(),
  132. $this->serverContainer->getUserManager(),
  133. $this->serverContainer->getCloudIdManager(),
  134. $this->serverContainer->getGlobalScaleConfig(),
  135. $this->serverContainer->getCloudFederationProviderManager(),
  136. $this->serverContainer->get(LoggerInterface::class),
  137. );
  138. }
  139. return $this->federatedProvider;
  140. }
  141. /**
  142. * Create the federated share provider
  143. *
  144. * @return ShareByMailProvider
  145. */
  146. protected function getShareByMailProvider() {
  147. if ($this->shareByMailProvider === null) {
  148. /*
  149. * Check if the app is enabled
  150. */
  151. $appManager = $this->serverContainer->getAppManager();
  152. if (!$appManager->isEnabledForUser('sharebymail')) {
  153. return null;
  154. }
  155. $settingsManager = new SettingsManager($this->serverContainer->getConfig());
  156. $this->shareByMailProvider = new ShareByMailProvider(
  157. $this->serverContainer->getConfig(),
  158. $this->serverContainer->getDatabaseConnection(),
  159. $this->serverContainer->get(ISecureRandom::class),
  160. $this->serverContainer->getUserManager(),
  161. $this->serverContainer->get(IRootFolder::class),
  162. $this->serverContainer->getL10N('sharebymail'),
  163. $this->serverContainer->get(LoggerInterface::class),
  164. $this->serverContainer->get(IMailer::class),
  165. $this->serverContainer->getURLGenerator(),
  166. $this->serverContainer->getActivityManager(),
  167. $settingsManager,
  168. $this->serverContainer->query(Defaults::class),
  169. $this->serverContainer->get(IHasher::class),
  170. $this->serverContainer->get(IEventDispatcher::class),
  171. $this->serverContainer->get(IManager::class)
  172. );
  173. }
  174. return $this->shareByMailProvider;
  175. }
  176. /**
  177. * Create the circle share provider
  178. *
  179. * @return FederatedShareProvider
  180. *
  181. * @suppress PhanUndeclaredClassMethod
  182. */
  183. protected function getShareByCircleProvider() {
  184. if ($this->circlesAreNotAvailable) {
  185. return null;
  186. }
  187. if (!$this->serverContainer->getAppManager()->isEnabledForUser('circles') ||
  188. !class_exists('\OCA\Circles\ShareByCircleProvider')
  189. ) {
  190. $this->circlesAreNotAvailable = true;
  191. return null;
  192. }
  193. if ($this->shareByCircleProvider === null) {
  194. $this->shareByCircleProvider = new \OCA\Circles\ShareByCircleProvider(
  195. $this->serverContainer->getDatabaseConnection(),
  196. $this->serverContainer->get(ISecureRandom::class),
  197. $this->serverContainer->getUserManager(),
  198. $this->serverContainer->get(IRootFolder::class),
  199. $this->serverContainer->getL10N('circles'),
  200. $this->serverContainer->getLogger(),
  201. $this->serverContainer->getURLGenerator()
  202. );
  203. }
  204. return $this->shareByCircleProvider;
  205. }
  206. /**
  207. * Create the room share provider
  208. *
  209. * @return RoomShareProvider
  210. */
  211. protected function getRoomShareProvider() {
  212. if ($this->roomShareProvider === null) {
  213. /*
  214. * Check if the app is enabled
  215. */
  216. $appManager = $this->serverContainer->getAppManager();
  217. if (!$appManager->isEnabledForUser('spreed')) {
  218. return null;
  219. }
  220. try {
  221. /**
  222. * @psalm-suppress UndefinedClass
  223. */
  224. $this->roomShareProvider = $this->serverContainer->get(RoomShareProvider::class);
  225. } catch (\Throwable $e) {
  226. $this->serverContainer->get(LoggerInterface::class)->error(
  227. $e->getMessage(),
  228. ['exception' => $e]
  229. );
  230. return null;
  231. }
  232. }
  233. return $this->roomShareProvider;
  234. }
  235. /**
  236. * @inheritdoc
  237. */
  238. public function getProvider($id) {
  239. $provider = null;
  240. if (isset($this->shareProviders[$id])) {
  241. return $this->shareProviders[$id];
  242. }
  243. if ($id === 'ocinternal') {
  244. $provider = $this->defaultShareProvider();
  245. } elseif ($id === 'ocFederatedSharing') {
  246. $provider = $this->federatedShareProvider();
  247. } elseif ($id === 'ocMailShare') {
  248. $provider = $this->getShareByMailProvider();
  249. } elseif ($id === 'ocCircleShare') {
  250. $provider = $this->getShareByCircleProvider();
  251. } elseif ($id === 'ocRoomShare') {
  252. $provider = $this->getRoomShareProvider();
  253. }
  254. foreach ($this->registeredShareProviders as $shareProvider) {
  255. try {
  256. /** @var IShareProvider $instance */
  257. $instance = $this->serverContainer->get($shareProvider);
  258. $this->shareProviders[$instance->identifier()] = $instance;
  259. } catch (\Throwable $e) {
  260. $this->serverContainer->get(LoggerInterface::class)->error(
  261. $e->getMessage(),
  262. ['exception' => $e]
  263. );
  264. }
  265. }
  266. if (isset($this->shareProviders[$id])) {
  267. $provider = $this->shareProviders[$id];
  268. }
  269. if ($provider === null) {
  270. throw new ProviderException('No provider with id .' . $id . ' found.');
  271. }
  272. return $provider;
  273. }
  274. /**
  275. * @inheritdoc
  276. */
  277. public function getProviderForType($shareType) {
  278. $provider = null;
  279. if ($shareType === IShare::TYPE_USER ||
  280. $shareType === IShare::TYPE_GROUP ||
  281. $shareType === IShare::TYPE_LINK
  282. ) {
  283. $provider = $this->defaultShareProvider();
  284. } elseif ($shareType === IShare::TYPE_REMOTE || $shareType === IShare::TYPE_REMOTE_GROUP) {
  285. $provider = $this->federatedShareProvider();
  286. } elseif ($shareType === IShare::TYPE_EMAIL) {
  287. $provider = $this->getShareByMailProvider();
  288. } elseif ($shareType === IShare::TYPE_CIRCLE) {
  289. $provider = $this->getShareByCircleProvider();
  290. } elseif ($shareType === IShare::TYPE_ROOM) {
  291. $provider = $this->getRoomShareProvider();
  292. } elseif ($shareType === IShare::TYPE_DECK) {
  293. $provider = $this->getProvider('deck');
  294. } elseif ($shareType === IShare::TYPE_SCIENCEMESH) {
  295. $provider = $this->getProvider('sciencemesh');
  296. }
  297. if ($provider === null) {
  298. throw new ProviderException('No share provider for share type ' . $shareType);
  299. }
  300. return $provider;
  301. }
  302. public function getAllProviders() {
  303. $shares = [$this->defaultShareProvider(), $this->federatedShareProvider()];
  304. $shareByMail = $this->getShareByMailProvider();
  305. if ($shareByMail !== null) {
  306. $shares[] = $shareByMail;
  307. }
  308. $shareByCircle = $this->getShareByCircleProvider();
  309. if ($shareByCircle !== null) {
  310. $shares[] = $shareByCircle;
  311. }
  312. $roomShare = $this->getRoomShareProvider();
  313. if ($roomShare !== null) {
  314. $shares[] = $roomShare;
  315. }
  316. foreach ($this->registeredShareProviders as $shareProvider) {
  317. try {
  318. /** @var IShareProvider $instance */
  319. $instance = $this->serverContainer->get($shareProvider);
  320. } catch (\Throwable $e) {
  321. $this->serverContainer->get(LoggerInterface::class)->error(
  322. $e->getMessage(),
  323. ['exception' => $e]
  324. );
  325. continue;
  326. }
  327. if (!isset($this->shareProviders[$instance->identifier()])) {
  328. $this->shareProviders[$instance->identifier()] = $instance;
  329. }
  330. $shares[] = $this->shareProviders[$instance->identifier()];
  331. }
  332. return $shares;
  333. }
  334. }