ProviderFactory.php 11 KB

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