BackendTest.php 11 KB

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