BackendTest.php 11 KB

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