OldGroupMembershipShares.php 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  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\Repair;
  8. use OCP\IDBConnection;
  9. use OCP\IGroupManager;
  10. use OCP\Migration\IOutput;
  11. use OCP\Migration\IRepairStep;
  12. use OCP\Share\IShare;
  13. class OldGroupMembershipShares implements IRepairStep {
  14. /**
  15. * @var array [gid => [uid => (bool)]]
  16. */
  17. protected $memberships;
  18. /**
  19. * @param IDBConnection $connection
  20. * @param IGroupManager $groupManager
  21. */
  22. public function __construct(
  23. protected IDBConnection $connection,
  24. protected IGroupManager $groupManager,
  25. ) {
  26. }
  27. /**
  28. * Returns the step's name
  29. *
  30. * @return string
  31. */
  32. public function getName() {
  33. return 'Remove shares of old group memberships';
  34. }
  35. /**
  36. * Run repair step.
  37. * Must throw exception on error.
  38. *
  39. * @throws \Exception in case of failure
  40. */
  41. public function run(IOutput $output) {
  42. $deletedEntries = 0;
  43. $query = $this->connection->getQueryBuilder();
  44. $query->select('s1.id')->selectAlias('s1.share_with', 'user')->selectAlias('s2.share_with', 'group')
  45. ->from('share', 's1')
  46. ->where($query->expr()->isNotNull('s1.parent'))
  47. // \OC\Share\Constant::$shareTypeGroupUserUnique === 2
  48. ->andWhere($query->expr()->eq('s1.share_type', $query->expr()->literal(2)))
  49. ->andWhere($query->expr()->isNotNull('s2.id'))
  50. ->andWhere($query->expr()->eq('s2.share_type', $query->expr()->literal(IShare::TYPE_GROUP)))
  51. ->leftJoin('s1', 'share', 's2', $query->expr()->eq('s1.parent', 's2.id'));
  52. $deleteQuery = $this->connection->getQueryBuilder();
  53. $deleteQuery->delete('share')
  54. ->where($query->expr()->eq('id', $deleteQuery->createParameter('share')));
  55. $result = $query->executeQuery();
  56. while ($row = $result->fetch()) {
  57. if (!$this->isMember($row['group'], $row['user'])) {
  58. $deletedEntries += $deleteQuery->setParameter('share', (int)$row['id'])
  59. ->executeStatement();
  60. }
  61. }
  62. $result->closeCursor();
  63. if ($deletedEntries) {
  64. $output->info('Removed ' . $deletedEntries . ' shares where user is not a member of the group anymore');
  65. }
  66. }
  67. /**
  68. * @param string $gid
  69. * @param string $uid
  70. * @return bool
  71. */
  72. protected function isMember($gid, $uid) {
  73. if (isset($this->memberships[$gid][$uid])) {
  74. return $this->memberships[$gid][$uid];
  75. }
  76. $isMember = $this->groupManager->isInGroup($uid, $gid);
  77. if (!isset($this->memberships[$gid])) {
  78. $this->memberships[$gid] = [];
  79. }
  80. $this->memberships[$gid][$uid] = $isMember;
  81. return $isMember;
  82. }
  83. }