BackendTest.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com>
  4. *
  5. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  6. * @author Joas Schilling <coding@schilljs.com>
  7. * @author Roeland Jago Douma <roeland@famdouma.nl>
  8. * @author Thomas Citharel <nextcloud@tcit.fr>
  9. *
  10. * @license GNU AGPL version 3 or any later version
  11. *
  12. * This program is free software: you can redistribute it and/or modify
  13. * it under the terms of the GNU Affero General Public License as
  14. * published by the Free Software Foundation, either version 3 of the
  15. * License, or (at your option) any later version.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU Affero General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU Affero General Public License
  23. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  24. *
  25. */
  26. namespace OCA\DAV\Tests\unit\CalDAV\Activity;
  27. use OCA\DAV\CalDAV\Activity\Backend;
  28. use OCA\DAV\CalDAV\Activity\Provider\Calendar;
  29. use OCP\Activity\IEvent;
  30. use OCP\Activity\IManager;
  31. use OCP\App\IAppManager;
  32. use OCP\IGroup;
  33. use OCP\IGroupManager;
  34. use OCP\IUser;
  35. use OCP\IUserManager;
  36. use OCP\IUserSession;
  37. use PHPUnit\Framework\MockObject\MockObject;
  38. use Test\TestCase;
  39. class BackendTest extends TestCase {
  40. /** @var IManager|MockObject */
  41. protected $activityManager;
  42. /** @var IGroupManager|MockObject */
  43. protected $groupManager;
  44. /** @var IUserSession|MockObject */
  45. protected $userSession;
  46. /** @var IAppManager|MockObject */
  47. protected $appManager;
  48. /** @var IUserManager|MockObject */
  49. protected $userManager;
  50. protected function setUp(): void {
  51. parent::setUp();
  52. $this->activityManager = $this->createMock(IManager::class);
  53. $this->groupManager = $this->createMock(IGroupManager::class);
  54. $this->userSession = $this->createMock(IUserSession::class);
  55. $this->appManager = $this->createMock(IAppManager::class);
  56. $this->userManager = $this->createMock(IUserManager::class);
  57. }
  58. /**
  59. * @param array $methods
  60. * @return Backend|MockObject
  61. */
  62. protected function getBackend(array $methods = []) {
  63. if (empty($methods)) {
  64. return new Backend(
  65. $this->activityManager,
  66. $this->groupManager,
  67. $this->userSession,
  68. $this->appManager,
  69. $this->userManager
  70. );
  71. } else {
  72. return $this->getMockBuilder(Backend::class)
  73. ->setConstructorArgs([
  74. $this->activityManager,
  75. $this->groupManager,
  76. $this->userSession,
  77. $this->appManager,
  78. $this->userManager
  79. ])
  80. ->onlyMethods($methods)
  81. ->getMock();
  82. }
  83. }
  84. public function dataCallTriggerCalendarActivity() {
  85. return [
  86. ['onCalendarAdd', [['data']], Calendar::SUBJECT_ADD, [['data'], [], []]],
  87. ['onCalendarUpdate', [['data'], ['shares'], ['changed-properties']], Calendar::SUBJECT_UPDATE, [['data'], ['shares'], ['changed-properties']]],
  88. ['onCalendarDelete', [['data'], ['shares']], Calendar::SUBJECT_DELETE, [['data'], ['shares'], []]],
  89. ['onCalendarPublication', [['data'], true], Calendar::SUBJECT_PUBLISH, [['data'], [], []]],
  90. ];
  91. }
  92. /**
  93. * @dataProvider dataCallTriggerCalendarActivity
  94. *
  95. * @param string $method
  96. * @param array $payload
  97. * @param string $expectedSubject
  98. * @param array $expectedPayload
  99. */
  100. public function testCallTriggerCalendarActivity($method, array $payload, $expectedSubject, array $expectedPayload): void {
  101. $backend = $this->getBackend(['triggerCalendarActivity']);
  102. $backend->expects($this->once())
  103. ->method('triggerCalendarActivity')
  104. ->willReturnCallback(function () use ($expectedPayload, $expectedSubject): void {
  105. $arguments = func_get_args();
  106. $this->assertSame($expectedSubject, array_shift($arguments));
  107. $this->assertEquals($expectedPayload, $arguments);
  108. });
  109. call_user_func_array([$backend, $method], $payload);
  110. }
  111. public function dataTriggerCalendarActivity() {
  112. return [
  113. // Add calendar
  114. [Calendar::SUBJECT_ADD, [], [], [], '', '', null, []],
  115. [Calendar::SUBJECT_ADD, [
  116. 'principaluri' => 'principal/user/admin',
  117. 'id' => 42,
  118. 'uri' => 'this-uri',
  119. '{DAV:}displayname' => 'Name of calendar',
  120. ], [], [], '', 'admin', null, ['admin']],
  121. [Calendar::SUBJECT_ADD, [
  122. 'principaluri' => 'principal/user/admin',
  123. 'id' => 42,
  124. 'uri' => 'this-uri',
  125. '{DAV:}displayname' => 'Name of calendar',
  126. ], [], [], 'test2', 'test2', null, ['admin']],
  127. // Update calendar
  128. [Calendar::SUBJECT_UPDATE, [], [], [], '', '', null, []],
  129. // No visible change - owner only
  130. [Calendar::SUBJECT_UPDATE, [
  131. 'principaluri' => 'principal/user/admin',
  132. 'id' => 42,
  133. 'uri' => 'this-uri',
  134. '{DAV:}displayname' => 'Name of calendar',
  135. ], ['shares'], [], '', 'admin', null, ['admin']],
  136. // Visible change
  137. [Calendar::SUBJECT_UPDATE, [
  138. 'principaluri' => 'principal/user/admin',
  139. 'id' => 42,
  140. 'uri' => 'this-uri',
  141. '{DAV:}displayname' => 'Name of calendar',
  142. ], ['shares'], ['{DAV:}displayname' => 'Name'], '', 'admin', ['user1'], ['user1', 'admin']],
  143. [Calendar::SUBJECT_UPDATE, [
  144. 'principaluri' => 'principal/user/admin',
  145. 'id' => 42,
  146. 'uri' => 'this-uri',
  147. '{DAV:}displayname' => 'Name of calendar',
  148. ], ['shares'], ['{DAV:}displayname' => 'Name'], 'test2', 'test2', ['user1'], ['user1', 'admin']],
  149. // Delete calendar
  150. [Calendar::SUBJECT_DELETE, [], [], [], '', '', null, []],
  151. [Calendar::SUBJECT_DELETE, [
  152. 'principaluri' => 'principal/user/admin',
  153. 'id' => 42,
  154. 'uri' => 'this-uri',
  155. '{DAV:}displayname' => 'Name of calendar',
  156. ], ['shares'], [], '', 'admin', [], ['admin']],
  157. [Calendar::SUBJECT_DELETE, [
  158. 'principaluri' => 'principal/user/admin',
  159. 'id' => 42,
  160. 'uri' => 'this-uri',
  161. '{DAV:}displayname' => 'Name of calendar',
  162. ], ['shares'], [], '', 'admin', ['user1'], ['user1', 'admin']],
  163. [Calendar::SUBJECT_DELETE, [
  164. 'principaluri' => 'principal/user/admin',
  165. 'id' => 42,
  166. 'uri' => 'this-uri',
  167. '{DAV:}displayname' => 'Name of calendar',
  168. ], ['shares'], [], 'test2', 'test2', ['user1'], ['user1', 'admin']],
  169. // Publish calendar
  170. [Calendar::SUBJECT_PUBLISH, [], [], [], '', '', null, []],
  171. [Calendar::SUBJECT_PUBLISH, [
  172. 'principaluri' => 'principal/user/admin',
  173. 'id' => 42,
  174. 'uri' => 'this-uri',
  175. '{DAV:}displayname' => 'Name of calendar',
  176. ], ['shares'], [], '', 'admin', [], ['admin']],
  177. // Unpublish calendar
  178. [Calendar::SUBJECT_UNPUBLISH, [], [], [], '', '', null, []],
  179. [Calendar::SUBJECT_UNPUBLISH, [
  180. 'principaluri' => 'principal/user/admin',
  181. 'id' => 42,
  182. 'uri' => 'this-uri',
  183. '{DAV:}displayname' => 'Name of calendar',
  184. ], ['shares'], [], '', 'admin', [], ['admin']],
  185. ];
  186. }
  187. /**
  188. * @dataProvider dataTriggerCalendarActivity
  189. * @param string $action
  190. * @param array $data
  191. * @param array $shares
  192. * @param array $changedProperties
  193. * @param string $currentUser
  194. * @param string $author
  195. * @param string[]|null $shareUsers
  196. * @param string[] $users
  197. */
  198. public function testTriggerCalendarActivity($action, array $data, array $shares, array $changedProperties, $currentUser, $author, $shareUsers, array $users): void {
  199. $backend = $this->getBackend(['getUsersForShares']);
  200. if ($shareUsers === null) {
  201. $backend->expects($this->never())
  202. ->method('getUsersForShares');
  203. } else {
  204. $backend->expects($this->once())
  205. ->method('getUsersForShares')
  206. ->with($shares)
  207. ->willReturn($shareUsers);
  208. }
  209. if ($author !== '') {
  210. if ($currentUser !== '') {
  211. $this->userSession->expects($this->once())
  212. ->method('getUser')
  213. ->willReturn($this->getUserMock($currentUser));
  214. } else {
  215. $this->userSession->expects($this->once())
  216. ->method('getUser')
  217. ->willReturn(null);
  218. }
  219. $event = $this->createMock(IEvent::class);
  220. $this->activityManager->expects($this->once())
  221. ->method('generateEvent')
  222. ->willReturn($event);
  223. $event->expects($this->once())
  224. ->method('setApp')
  225. ->with('dav')
  226. ->willReturnSelf();
  227. $event->expects($this->once())
  228. ->method('setObject')
  229. ->with('calendar', $data['id'])
  230. ->willReturnSelf();
  231. $event->expects($this->once())
  232. ->method('setType')
  233. ->with('calendar')
  234. ->willReturnSelf();
  235. $event->expects($this->once())
  236. ->method('setAuthor')
  237. ->with($author)
  238. ->willReturnSelf();
  239. $this->userManager->expects($action === Calendar::SUBJECT_DELETE ? $this->exactly(sizeof($users)) : $this->never())
  240. ->method('userExists')
  241. ->willReturn(true);
  242. $event->expects($this->exactly(sizeof($users)))
  243. ->method('setAffectedUser')
  244. ->willReturnSelf();
  245. $event->expects($this->exactly(sizeof($users)))
  246. ->method('setSubject')
  247. ->willReturnSelf();
  248. $this->activityManager->expects($this->exactly(sizeof($users)))
  249. ->method('publish')
  250. ->with($event);
  251. } else {
  252. $this->activityManager->expects($this->never())
  253. ->method('generateEvent');
  254. }
  255. $this->invokePrivate($backend, 'triggerCalendarActivity', [$action, $data, $shares, $changedProperties]);
  256. }
  257. public function testUserDeletionDoesNotCreateActivity(): void {
  258. $backend = $this->getBackend();
  259. $this->userManager->expects($this->once())
  260. ->method('userExists')
  261. ->willReturn(false);
  262. $this->activityManager->expects($this->never())
  263. ->method('publish');
  264. $this->invokePrivate($backend, 'triggerCalendarActivity', [Calendar::SUBJECT_DELETE, [
  265. 'principaluri' => 'principal/user/admin',
  266. 'id' => 42,
  267. 'uri' => 'this-uri',
  268. '{DAV:}displayname' => 'Name of calendar',
  269. ], [], []]);
  270. }
  271. public function dataGetUsersForShares() {
  272. return [
  273. [
  274. [],
  275. [],
  276. [],
  277. ],
  278. [
  279. [
  280. ['{http://owncloud.org/ns}principal' => 'principal/users/user1'],
  281. ['{http://owncloud.org/ns}principal' => 'principal/users/user2'],
  282. ['{http://owncloud.org/ns}principal' => 'principal/users/user2'],
  283. ['{http://owncloud.org/ns}principal' => 'principal/users/user2'],
  284. ['{http://owncloud.org/ns}principal' => 'principal/users/user3'],
  285. ],
  286. [],
  287. ['user1', 'user2', 'user3'],
  288. ],
  289. [
  290. [
  291. ['{http://owncloud.org/ns}principal' => 'principal/users/user1'],
  292. ['{http://owncloud.org/ns}principal' => 'principal/users/user2'],
  293. ['{http://owncloud.org/ns}principal' => 'principal/users/user2'],
  294. ['{http://owncloud.org/ns}principal' => 'principal/groups/group2'],
  295. ['{http://owncloud.org/ns}principal' => 'principal/groups/group3'],
  296. ],
  297. ['group2' => null, 'group3' => null],
  298. ['user1', 'user2'],
  299. ],
  300. [
  301. [
  302. ['{http://owncloud.org/ns}principal' => 'principal/users/user1'],
  303. ['{http://owncloud.org/ns}principal' => 'principal/users/user2'],
  304. ['{http://owncloud.org/ns}principal' => 'principal/users/user2'],
  305. ['{http://owncloud.org/ns}principal' => 'principal/groups/group2'],
  306. ['{http://owncloud.org/ns}principal' => 'principal/groups/group3'],
  307. ],
  308. ['group2' => ['user1', 'user2', 'user3'], 'group3' => ['user2', 'user3', 'user4']],
  309. ['user1', 'user2', 'user3', 'user4'],
  310. ],
  311. ];
  312. }
  313. /**
  314. * @dataProvider dataGetUsersForShares
  315. * @param array $shares
  316. * @param array $groups
  317. * @param array $expected
  318. */
  319. public function testGetUsersForShares(array $shares, array $groups, array $expected): void {
  320. $backend = $this->getBackend();
  321. $getGroups = [];
  322. foreach ($groups as $gid => $members) {
  323. if ($members === null) {
  324. $getGroups[] = [$gid, null];
  325. continue;
  326. }
  327. $group = $this->createMock(IGroup::class);
  328. $group->expects($this->once())
  329. ->method('getUsers')
  330. ->willReturn($this->getUsers($members));
  331. $getGroups[] = [$gid, $group];
  332. }
  333. $this->groupManager->expects($this->exactly(sizeof($getGroups)))
  334. ->method('get')
  335. ->willReturnMap($getGroups);
  336. $users = $this->invokePrivate($backend, 'getUsersForShares', [$shares]);
  337. sort($users);
  338. $this->assertEquals($expected, $users);
  339. }
  340. /**
  341. * @param string[] $users
  342. * @return IUser[]|MockObject[]
  343. */
  344. protected function getUsers(array $users) {
  345. $list = [];
  346. foreach ($users as $user) {
  347. $list[] = $this->getUserMock($user);
  348. }
  349. return $list;
  350. }
  351. /**
  352. * @param string $uid
  353. * @return IUser|MockObject
  354. */
  355. protected function getUserMock($uid) {
  356. $user = $this->createMock(IUser::class);
  357. $user->expects($this->once())
  358. ->method('getUID')
  359. ->willReturn($uid);
  360. return $user;
  361. }
  362. }