RepairInvalidSharesTest.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. <?php
  2. /**
  3. * Copyright (c) 2015 Vincent Petry <pvince81@owncloud.com>
  4. * This file is licensed under the Affero General Public License version 3 or
  5. * later.
  6. * See the COPYING-README file.
  7. */
  8. namespace Test\Repair;
  9. use OC\Repair\RepairInvalidShares;
  10. use OCP\IConfig;
  11. use OCP\Migration\IOutput;
  12. use OCP\Migration\IRepairStep;
  13. use OCP\Share\IShare;
  14. use Test\TestCase;
  15. /**
  16. * Tests for repairing invalid shares
  17. *
  18. * @group DB
  19. *
  20. * @see \OC\Repair\RepairInvalidShares
  21. */
  22. class RepairInvalidSharesTest extends TestCase {
  23. /** @var IRepairStep */
  24. private $repair;
  25. /** @var \OCP\IDBConnection */
  26. private $connection;
  27. protected function setUp(): void {
  28. parent::setUp();
  29. $config = $this->getMockBuilder(IConfig::class)
  30. ->disableOriginalConstructor()
  31. ->getMock();
  32. $config->expects($this->any())
  33. ->method('getSystemValueString')
  34. ->with('version')
  35. ->willReturn('12.0.0.0');
  36. $this->connection = \OC::$server->getDatabaseConnection();
  37. $this->deleteAllShares();
  38. /** @var \OCP\IConfig $config */
  39. $this->repair = new RepairInvalidShares($config, $this->connection);
  40. }
  41. protected function tearDown(): void {
  42. $this->deleteAllShares();
  43. parent::tearDown();
  44. }
  45. protected function deleteAllShares() {
  46. $qb = $this->connection->getQueryBuilder();
  47. $qb->delete('share')->execute();
  48. }
  49. /**
  50. * Test remove shares where the parent share does not exist anymore
  51. */
  52. public function testSharesNonExistingParent() {
  53. $qb = $this->connection->getQueryBuilder();
  54. $shareValues = [
  55. 'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
  56. 'share_with' => $qb->expr()->literal('recipientuser1'),
  57. 'uid_owner' => $qb->expr()->literal('user1'),
  58. 'item_type' => $qb->expr()->literal('folder'),
  59. 'item_source' => $qb->expr()->literal(123),
  60. 'item_target' => $qb->expr()->literal('/123'),
  61. 'file_source' => $qb->expr()->literal(123),
  62. 'file_target' => $qb->expr()->literal('/test'),
  63. 'permissions' => $qb->expr()->literal(1),
  64. 'stime' => $qb->expr()->literal(time()),
  65. 'expiration' => $qb->expr()->literal('2015-09-25 00:00:00')
  66. ];
  67. // valid share
  68. $qb = $this->connection->getQueryBuilder();
  69. $qb->insert('share')
  70. ->values($shareValues)
  71. ->execute();
  72. $parent = $this->getLastShareId();
  73. // share with existing parent
  74. $qb = $this->connection->getQueryBuilder();
  75. $qb->insert('share')
  76. ->values(array_merge($shareValues, [
  77. 'parent' => $qb->expr()->literal($parent),
  78. ]))->execute();
  79. $validChild = $this->getLastShareId();
  80. // share with non-existing parent
  81. $qb = $this->connection->getQueryBuilder();
  82. $qb->insert('share')
  83. ->values(array_merge($shareValues, [
  84. 'parent' => $qb->expr()->literal($parent + 100),
  85. ]))->execute();
  86. $invalidChild = $this->getLastShareId();
  87. $query = $this->connection->getQueryBuilder();
  88. $result = $query->select('id')
  89. ->from('share')
  90. ->orderBy('id', 'ASC')
  91. ->execute();
  92. $rows = $result->fetchAll();
  93. $this->assertEquals([['id' => $parent], ['id' => $validChild], ['id' => $invalidChild]], $rows);
  94. $result->closeCursor();
  95. /** @var IOutput | \PHPUnit\Framework\MockObject\MockObject $outputMock */
  96. $outputMock = $this->getMockBuilder('\OCP\Migration\IOutput')
  97. ->disableOriginalConstructor()
  98. ->getMock();
  99. $this->repair->run($outputMock);
  100. $query = $this->connection->getQueryBuilder();
  101. $result = $query->select('id')
  102. ->from('share')
  103. ->orderBy('id', 'ASC')
  104. ->execute();
  105. $rows = $result->fetchAll();
  106. $this->assertEquals([['id' => $parent], ['id' => $validChild]], $rows);
  107. $result->closeCursor();
  108. }
  109. public function fileSharePermissionsProvider() {
  110. return [
  111. // unchanged for folder
  112. [
  113. 'folder',
  114. 31,
  115. 31,
  116. ],
  117. // unchanged for read-write + share
  118. [
  119. 'file',
  120. \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE,
  121. \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE,
  122. ],
  123. // fixed for all perms
  124. [
  125. 'file',
  126. \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE | \OCP\Constants::PERMISSION_SHARE,
  127. \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE,
  128. ],
  129. ];
  130. }
  131. /**
  132. * Test adjusting file share permissions
  133. *
  134. * @dataProvider fileSharePermissionsProvider
  135. */
  136. public function testFileSharePermissions($itemType, $testPerms, $expectedPerms) {
  137. $qb = $this->connection->getQueryBuilder();
  138. $qb->insert('share')
  139. ->values([
  140. 'share_type' => $qb->expr()->literal(IShare::TYPE_LINK),
  141. 'uid_owner' => $qb->expr()->literal('user1'),
  142. 'item_type' => $qb->expr()->literal($itemType),
  143. 'item_source' => $qb->expr()->literal(123),
  144. 'item_target' => $qb->expr()->literal('/123'),
  145. 'file_source' => $qb->expr()->literal(123),
  146. 'file_target' => $qb->expr()->literal('/test'),
  147. 'permissions' => $qb->expr()->literal($testPerms),
  148. 'stime' => $qb->expr()->literal(time()),
  149. ])
  150. ->execute();
  151. $shareId = $this->getLastShareId();
  152. /** @var IOutput | \PHPUnit\Framework\MockObject\MockObject $outputMock */
  153. $outputMock = $this->getMockBuilder('\OCP\Migration\IOutput')
  154. ->disableOriginalConstructor()
  155. ->getMock();
  156. $this->repair->run($outputMock);
  157. $results = $this->connection->getQueryBuilder()
  158. ->select('*')
  159. ->from('share')
  160. ->orderBy('permissions', 'ASC')
  161. ->execute()
  162. ->fetchAll();
  163. $this->assertCount(1, $results);
  164. $updatedShare = $results[0];
  165. $this->assertEquals($expectedPerms, $updatedShare['permissions']);
  166. }
  167. /**
  168. * @return int
  169. */
  170. protected function getLastShareId() {
  171. return $this->connection->lastInsertId('*PREFIX*share');
  172. }
  173. }