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.

RepairInvalidSharesTest.php 9.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  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 OC\Share\Constants;
  11. use OCP\Migration\IOutput;
  12. use OCP\Migration\IRepairStep;
  13. use Test\TestCase;
  14. /**
  15. * Tests for repairing invalid shares
  16. *
  17. * @group DB
  18. *
  19. * @see \OC\Repair\RepairInvalidShares
  20. */
  21. class RepairInvalidSharesTest extends TestCase {
  22. /** @var IRepairStep */
  23. private $repair;
  24. /** @var \OCP\IDBConnection */
  25. private $connection;
  26. protected function setUp() {
  27. parent::setUp();
  28. $config = $this->getMockBuilder('OCP\IConfig')
  29. ->disableOriginalConstructor()
  30. ->getMock();
  31. $config->expects($this->any())
  32. ->method('getSystemValue')
  33. ->with('version')
  34. ->will($this->returnValue('8.0.0.0'));
  35. $this->connection = \OC::$server->getDatabaseConnection();
  36. $this->deleteAllShares();
  37. /** @var \OCP\IConfig $config */
  38. $this->repair = new RepairInvalidShares($config, $this->connection);
  39. }
  40. protected function tearDown() {
  41. $this->deleteAllShares();
  42. parent::tearDown();
  43. }
  44. protected function deleteAllShares() {
  45. $qb = $this->connection->getQueryBuilder();
  46. $qb->delete('share')->execute();
  47. }
  48. /**
  49. * Test remove expiration date for non-link shares
  50. */
  51. public function testRemoveExpirationDateForNonLinkShares() {
  52. // user share with bogus expiration date
  53. $qb = $this->connection->getQueryBuilder();
  54. $qb->insert('share')
  55. ->values([
  56. 'share_type' => $qb->expr()->literal(Constants::SHARE_TYPE_USER),
  57. 'share_with' => $qb->expr()->literal('recipientuser1'),
  58. 'uid_owner' => $qb->expr()->literal('user1'),
  59. 'item_type' => $qb->expr()->literal('folder'),
  60. 'item_source' => $qb->expr()->literal(123),
  61. 'item_target' => $qb->expr()->literal('/123'),
  62. 'file_source' => $qb->expr()->literal(123),
  63. 'file_target' => $qb->expr()->literal('/test'),
  64. 'permissions' => $qb->expr()->literal(1),
  65. 'stime' => $qb->expr()->literal(time()),
  66. 'expiration' => $qb->expr()->literal('2015-09-25 00:00:00')
  67. ])
  68. ->execute();
  69. $bogusShareId = $this->getLastShareId();
  70. // link share with expiration date
  71. $qb = $this->connection->getQueryBuilder();
  72. $qb->insert('share')
  73. ->values([
  74. 'share_type' => $qb->expr()->literal(Constants::SHARE_TYPE_LINK),
  75. 'uid_owner' => $qb->expr()->literal('user1'),
  76. 'item_type' => $qb->expr()->literal('folder'),
  77. 'item_source' => $qb->expr()->literal(123),
  78. 'item_target' => $qb->expr()->literal('/123'),
  79. 'file_source' => $qb->expr()->literal(123),
  80. 'file_target' => $qb->expr()->literal('/test'),
  81. 'permissions' => $qb->expr()->literal(1),
  82. 'stime' => $qb->expr()->literal(time()),
  83. 'expiration' => $qb->expr()->literal('2015-09-25 00:00:00'),
  84. 'token' => $qb->expr()->literal('abcdefg')
  85. ])->execute();
  86. /** @var IOutput | \PHPUnit_Framework_MockObject_MockObject $outputMock */
  87. $outputMock = $this->getMockBuilder('\OCP\Migration\IOutput')
  88. ->disableOriginalConstructor()
  89. ->getMock();
  90. $this->repair->run($outputMock);
  91. $results = $this->connection->getQueryBuilder()
  92. ->select('*')
  93. ->from('share')
  94. ->orderBy('share_type', 'ASC')
  95. ->execute()
  96. ->fetchAll();
  97. $this->assertCount(2, $results);
  98. $userShare = $results[0];
  99. $linkShare = $results[1];
  100. $this->assertEquals($bogusShareId, $userShare['id'], 'sanity check');
  101. $this->assertNull($userShare['expiration'], 'bogus expiration date was removed');
  102. $this->assertNotNull($linkShare['expiration'], 'valid link share expiration date still there');
  103. }
  104. /**
  105. * Test remove expiration date for non-link shares
  106. */
  107. public function testAddShareLinkDeletePermission() {
  108. $oldPerms = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE;
  109. $newPerms = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE;
  110. // share with old permissions
  111. $qb = $this->connection->getQueryBuilder();
  112. $qb->insert('share')
  113. ->values([
  114. 'share_type' => $qb->expr()->literal(Constants::SHARE_TYPE_LINK),
  115. 'uid_owner' => $qb->expr()->literal('user1'),
  116. 'item_type' => $qb->expr()->literal('folder'),
  117. 'item_source' => $qb->expr()->literal(123),
  118. 'item_target' => $qb->expr()->literal('/123'),
  119. 'file_source' => $qb->expr()->literal(123),
  120. 'file_target' => $qb->expr()->literal('/test'),
  121. 'permissions' => $qb->expr()->literal($oldPerms),
  122. 'stime' => $qb->expr()->literal(time()),
  123. ])
  124. ->execute();
  125. $bogusShareId = $this->getLastShareId();
  126. // share with read-only permissions
  127. $qb = $this->connection->getQueryBuilder();
  128. $qb->insert('share')
  129. ->values([
  130. 'share_type' => $qb->expr()->literal(Constants::SHARE_TYPE_LINK),
  131. 'uid_owner' => $qb->expr()->literal('user1'),
  132. 'item_type' => $qb->expr()->literal('folder'),
  133. 'item_source' => $qb->expr()->literal(123),
  134. 'item_target' => $qb->expr()->literal('/123'),
  135. 'file_source' => $qb->expr()->literal(123),
  136. 'file_target' => $qb->expr()->literal('/test'),
  137. 'permissions' => $qb->expr()->literal(\OCP\Constants::PERMISSION_READ),
  138. 'stime' => $qb->expr()->literal(time()),
  139. ])
  140. ->execute();
  141. $keepThisShareId = $this->getLastShareId();
  142. // user share to keep
  143. $qb = $this->connection->getQueryBuilder();
  144. $qb->insert('share')
  145. ->values([
  146. 'share_type' => $qb->expr()->literal(Constants::SHARE_TYPE_USER),
  147. 'share_with' => $qb->expr()->literal('recipientuser1'),
  148. 'uid_owner' => $qb->expr()->literal('user1'),
  149. 'item_type' => $qb->expr()->literal('folder'),
  150. 'item_source' => $qb->expr()->literal(123),
  151. 'item_target' => $qb->expr()->literal('/123'),
  152. 'file_source' => $qb->expr()->literal(123),
  153. 'file_target' => $qb->expr()->literal('/test'),
  154. 'permissions' => $qb->expr()->literal(3),
  155. 'stime' => $qb->expr()->literal(time()),
  156. ])
  157. ->execute();
  158. $keepThisShareId2 = $this->getLastShareId();
  159. /** @var IOutput | \PHPUnit_Framework_MockObject_MockObject $outputMock */
  160. $outputMock = $this->getMockBuilder('\OCP\Migration\IOutput')
  161. ->disableOriginalConstructor()
  162. ->getMock();
  163. $this->repair->run($outputMock);
  164. $results = $this->connection->getQueryBuilder()
  165. ->select('*')
  166. ->from('share')
  167. ->orderBy('permissions', 'ASC')
  168. ->execute()
  169. ->fetchAll();
  170. $this->assertCount(3, $results);
  171. $untouchedShare = $results[0];
  172. $untouchedShare2 = $results[1];
  173. $updatedShare = $results[2];
  174. $this->assertEquals($keepThisShareId, $untouchedShare['id'], 'sanity check');
  175. $this->assertEquals($keepThisShareId2, $untouchedShare2['id'], 'sanity check');
  176. $this->assertEquals($bogusShareId, $updatedShare['id'], 'sanity check');
  177. $this->assertEquals($newPerms, $updatedShare['permissions'], 'delete permission was added');
  178. }
  179. /**
  180. * Test remove shares where the parent share does not exist anymore
  181. */
  182. public function testSharesNonExistingParent() {
  183. $qb = $this->connection->getQueryBuilder();
  184. $shareValues = [
  185. 'share_type' => $qb->expr()->literal(Constants::SHARE_TYPE_USER),
  186. 'share_with' => $qb->expr()->literal('recipientuser1'),
  187. 'uid_owner' => $qb->expr()->literal('user1'),
  188. 'item_type' => $qb->expr()->literal('folder'),
  189. 'item_source' => $qb->expr()->literal(123),
  190. 'item_target' => $qb->expr()->literal('/123'),
  191. 'file_source' => $qb->expr()->literal(123),
  192. 'file_target' => $qb->expr()->literal('/test'),
  193. 'permissions' => $qb->expr()->literal(1),
  194. 'stime' => $qb->expr()->literal(time()),
  195. 'expiration' => $qb->expr()->literal('2015-09-25 00:00:00')
  196. ];
  197. // valid share
  198. $qb = $this->connection->getQueryBuilder();
  199. $qb->insert('share')
  200. ->values($shareValues)
  201. ->execute();
  202. $parent = $this->getLastShareId();
  203. // share with existing parent
  204. $qb = $this->connection->getQueryBuilder();
  205. $qb->insert('share')
  206. ->values(array_merge($shareValues, [
  207. 'parent' => $qb->expr()->literal($parent),
  208. ]))->execute();
  209. $validChild = $this->getLastShareId();
  210. // share with non-existing parent
  211. $qb = $this->connection->getQueryBuilder();
  212. $qb->insert('share')
  213. ->values(array_merge($shareValues, [
  214. 'parent' => $qb->expr()->literal($parent + 100),
  215. ]))->execute();
  216. $invalidChild = $this->getLastShareId();
  217. $query = $this->connection->getQueryBuilder();
  218. $result = $query->select('id')
  219. ->from('share')
  220. ->orderBy('id', 'ASC')
  221. ->execute();
  222. $rows = $result->fetchAll();
  223. $this->assertEquals([['id' => $parent], ['id' => $validChild], ['id' => $invalidChild]], $rows);
  224. $result->closeCursor();
  225. /** @var IOutput | \PHPUnit_Framework_MockObject_MockObject $outputMock */
  226. $outputMock = $this->getMockBuilder('\OCP\Migration\IOutput')
  227. ->disableOriginalConstructor()
  228. ->getMock();
  229. $this->repair->run($outputMock);
  230. $query = $this->connection->getQueryBuilder();
  231. $result = $query->select('id')
  232. ->from('share')
  233. ->orderBy('id', 'ASC')
  234. ->execute();
  235. $rows = $result->fetchAll();
  236. $this->assertEquals([['id' => $parent], ['id' => $validChild]], $rows);
  237. $result->closeCursor();
  238. }
  239. /**
  240. * @return int
  241. */
  242. protected function getLastShareId() {
  243. return $this->connection->lastInsertId('*PREFIX*share');
  244. }
  245. }