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.

140 lines
4.1 KiB

  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. *
  5. * @copyright Copyright (c) 2018, Daniel Calviño Sánchez (danxuliu@gmail.com)
  6. *
  7. * @license GNU AGPL version 3 or any later version
  8. *
  9. * This program is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU Affero General Public License as
  11. * published by the Free Software Foundation, either version 3 of the
  12. * License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU Affero General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Affero General Public License
  20. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21. *
  22. */
  23. namespace OCA\Talk\Files;
  24. use OCA\Files_Sharing\SharedStorage;
  25. use OCP\Files\Config\ICachedMountInfo;
  26. use OCP\Files\Config\IUserMountCache;
  27. use OCP\Files\FileInfo;
  28. use OCP\Files\IRootFolder;
  29. use OCP\Files\Node;
  30. use OCP\ISession;
  31. use OCP\Share\Exceptions\ShareNotFound;
  32. use OCP\Share\IManager as IShareManager;
  33. class Util {
  34. private IRootFolder $rootFolder;
  35. private ISession $session;
  36. private IShareManager $shareManager;
  37. private IUserMountCache $userMountCache;
  38. /** @var array[] */
  39. private array $accessLists = [];
  40. /** @var bool[] */
  41. private array $publicAccessLists = [];
  42. public function __construct(IRootFolder $rootFolder,
  43. ISession $session,
  44. IShareManager $shareManager,
  45. IUserMountCache $userMountCache) {
  46. $this->rootFolder = $rootFolder;
  47. $this->session = $session;
  48. $this->shareManager = $shareManager;
  49. $this->userMountCache = $userMountCache;
  50. }
  51. public function getUsersWithAccessFile(string $fileId): array {
  52. if (!isset($this->accessLists[$fileId])) {
  53. $nodes = $this->rootFolder->getById((int) $fileId);
  54. if (empty($nodes)) {
  55. return [];
  56. }
  57. $node = array_shift($nodes);
  58. $accessList = $this->shareManager->getAccessList($node);
  59. if (!$node->getStorage()->instanceOfStorage(SharedStorage::class)) {
  60. // The file is not a shared file,
  61. // let's check the accesslist for mount points of groupfolders and external storages
  62. $mountsForFile = $this->userMountCache->getMountsForFileId($fileId);
  63. $affectedUserIds = array_map(function (ICachedMountInfo $mount) {
  64. return $mount->getUser()->getUID();
  65. }, $mountsForFile);
  66. $accessList['users'] = array_unique(array_merge($affectedUserIds, $accessList['users']));
  67. }
  68. $this->accessLists[$fileId] = $accessList['users'];
  69. }
  70. return $this->accessLists[$fileId];
  71. }
  72. public function canUserAccessFile(string $fileId, string $userId): bool {
  73. return \in_array($userId, $this->getUsersWithAccessFile($fileId), true);
  74. }
  75. public function canGuestsAccessFile(string $fileId): bool {
  76. if (!isset($this->publicAccessLists[$fileId])) {
  77. $nodes = $this->rootFolder->getById((int) $fileId);
  78. if (empty($nodes)) {
  79. return false;
  80. }
  81. $node = array_shift($nodes);
  82. $accessList = $this->shareManager->getAccessList($node, false);
  83. $this->publicAccessLists[$fileId] = $accessList['public'];
  84. }
  85. return $this->publicAccessLists[$fileId] === true;
  86. }
  87. public function canGuestAccessFile(string $shareToken): bool {
  88. try {
  89. $share = $this->shareManager->getShareByToken($shareToken);
  90. if ($share->getPassword() !== null) {
  91. $shareId = $this->session->get('public_link_authenticated');
  92. if ($share->getId() !== $shareId) {
  93. throw new ShareNotFound();
  94. }
  95. }
  96. return true;
  97. } catch (ShareNotFound $e) {
  98. return false;
  99. }
  100. }
  101. /**
  102. * Returns any node of the file that is public and owned by the user, or
  103. * that the user has direct access to.
  104. *
  105. * @param string $fileId
  106. * @param string $userId
  107. * @return Node|null
  108. */
  109. public function getAnyNodeOfFileAccessibleByUser(string $fileId, string $userId): ?Node {
  110. $userFolder = $this->rootFolder->getUserFolder($userId);
  111. $nodes = $userFolder->getById((int) $fileId);
  112. $nodes = array_filter($nodes, static function (Node $node) {
  113. return $node->getType() === FileInfo::TYPE_FILE;
  114. });
  115. if (empty($nodes)) {
  116. return null;
  117. }
  118. return array_shift($nodes);
  119. }
  120. }