CollaborationContext.php 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
  5. * SPDX-License-Identifier: AGPL-3.0-or-later
  6. */
  7. use Behat\Behat\Context\Context;
  8. use Behat\Gherkin\Node\TableNode;
  9. use GuzzleHttp\Client;
  10. use PHPUnit\Framework\Assert;
  11. require __DIR__ . '/../../vendor/autoload.php';
  12. class CollaborationContext implements Context {
  13. use Provisioning;
  14. use AppConfiguration;
  15. use WebDav;
  16. /**
  17. * @Then /^get autocomplete for "([^"]*)"$/
  18. * @param TableNode|null $formData
  19. */
  20. public function getAutocompleteForUser(string $search, TableNode $formData): void {
  21. $this->getAutocompleteWithType(0, $search, $formData);
  22. }
  23. /**
  24. * @Then /^get email autocomplete for "([^"]*)"$/
  25. * @param TableNode|null $formData
  26. */
  27. public function getAutocompleteForEmail(string $search, TableNode $formData): void {
  28. $this->getAutocompleteWithType(4, $search, $formData);
  29. }
  30. private function getAutocompleteWithType(int $type, string $search, TableNode $formData): void {
  31. $query = $search === 'null' ? null : $search;
  32. $this->sendRequestForJSON('GET', '/core/autocomplete/get?itemType=files&itemId=123&shareTypes[]=' . $type . '&search=' . $query, [
  33. 'itemType' => 'files',
  34. 'itemId' => '123',
  35. 'search' => $query,
  36. ]);
  37. $this->theHTTPStatusCodeShouldBe(200);
  38. $data = json_decode($this->response->getBody()->getContents(), true);
  39. $suggestions = $data['ocs']['data'];
  40. Assert::assertCount(count($formData->getHash()), $suggestions, 'Suggestion count does not match');
  41. Assert::assertEquals($formData->getHash(), array_map(static function ($suggestion, $expected) {
  42. $data = [];
  43. if (isset($expected['id'])) {
  44. $data['id'] = $suggestion['id'];
  45. }
  46. if (isset($expected['source'])) {
  47. $data['source'] = $suggestion['source'];
  48. }
  49. if (isset($expected['status'])) {
  50. $data['status'] = json_encode($suggestion['status']);
  51. }
  52. return $data;
  53. }, $suggestions, $formData->getHash()));
  54. }
  55. /**
  56. * @Given /^there is a contact in an addressbook$/
  57. */
  58. public function thereIsAContactInAnAddressbook() {
  59. $this->usingNewDavPath();
  60. try {
  61. $destination = '/users/admin/myaddressbook';
  62. $data = '<x0:mkcol xmlns:x0="DAV:"><x0:set><x0:prop><x0:resourcetype><x0:collection/><x4:addressbook xmlns:x4="urn:ietf:params:xml:ns:carddav"/></x0:resourcetype><x0:displayname>myaddressbook</x0:displayname></x0:prop></x0:set></x0:mkcol>';
  63. $this->response = $this->makeDavRequest($this->currentUser, "MKCOL", $destination, ['Content-Type' => 'application/xml'], $data, "addressbooks");
  64. } catch (\GuzzleHttp\Exception\ServerException $e) {
  65. // 5xx responses cause a server exception
  66. $this->response = $e->getResponse();
  67. } catch (\GuzzleHttp\Exception\ClientException $e) {
  68. // 4xx responses cause a client exception
  69. $this->response = $e->getResponse();
  70. }
  71. try {
  72. $destination = '/users/admin/myaddressbook/contact1.vcf';
  73. $data = <<<EOF
  74. BEGIN:VCARD
  75. VERSION:4.0
  76. PRODID:-//Nextcloud Contacts v4.0.2
  77. UID:a0f4088a-4dca-4308-9b63-09a1ebcf78f3
  78. FN:A person
  79. ADR;TYPE=HOME:;;;;;;
  80. EMAIL;TYPE=HOME:user@example.com
  81. REV;VALUE=DATE-AND-OR-TIME:20211130T140111Z
  82. END:VCARD
  83. EOF;
  84. $this->response = $this->makeDavRequest($this->currentUser, "PUT", $destination, [], $data, "addressbooks");
  85. } catch (\GuzzleHttp\Exception\ServerException $e) {
  86. // 5xx responses cause a server exception
  87. $this->response = $e->getResponse();
  88. } catch (\GuzzleHttp\Exception\ClientException $e) {
  89. // 4xx responses cause a client exception
  90. $this->response = $e->getResponse();
  91. }
  92. }
  93. protected function resetAppConfigs(): void {
  94. $this->deleteServerConfig('core', 'shareapi_allow_share_dialog_user_enumeration');
  95. $this->deleteServerConfig('core', 'shareapi_restrict_user_enumeration_to_group');
  96. $this->deleteServerConfig('core', 'shareapi_restrict_user_enumeration_to_phone');
  97. $this->deleteServerConfig('core', 'shareapi_restrict_user_enumeration_full_match');
  98. $this->deleteServerConfig('core', 'shareapi_restrict_user_enumeration_full_match_userid');
  99. $this->deleteServerConfig('core', 'shareapi_restrict_user_enumeration_full_match_email');
  100. $this->deleteServerConfig('core', 'shareapi_restrict_user_enumeration_full_match_ignore_second_dn');
  101. $this->deleteServerConfig('core', 'shareapi_only_share_with_group_members');
  102. }
  103. /**
  104. * @Given /^user "([^"]*)" has status "([^"]*)"$/
  105. * @param string $user
  106. * @param string $status
  107. */
  108. public function assureUserHasStatus($user, $status) {
  109. $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/apps/user_status/api/v1/user_status/status";
  110. $client = new Client();
  111. $options = [
  112. 'headers' => [
  113. 'OCS-APIREQUEST' => 'true',
  114. ],
  115. ];
  116. if ($user === 'admin') {
  117. $options['auth'] = $this->adminUser;
  118. } else {
  119. $options['auth'] = [$user, $this->regularUser];
  120. }
  121. $options['form_params'] = [
  122. 'statusType' => $status
  123. ];
  124. $this->response = $client->put($fullUrl, $options);
  125. $this->theHTTPStatusCodeShouldBe(200);
  126. $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/apps/user_status/api/v1/user_status";
  127. unset($options['form_params']);
  128. $this->response = $client->get($fullUrl, $options);
  129. $this->theHTTPStatusCodeShouldBe(200);
  130. $returnedStatus = json_decode(json_encode(simplexml_load_string($this->response->getBody()->getContents())->data), true)['status'];
  131. Assert::assertEquals($status, $returnedStatus);
  132. }
  133. /**
  134. * @param string $user
  135. * @return null|array
  136. */
  137. public function getStatusList(string $user): ?array {
  138. $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/apps/user_status/api/v1/statuses";
  139. $client = new Client();
  140. $options = [
  141. 'headers' => [
  142. 'OCS-APIREQUEST' => 'true',
  143. ],
  144. ];
  145. if ($user === 'admin') {
  146. $options['auth'] = $this->adminUser;
  147. } else {
  148. $options['auth'] = [$user, $this->regularUser];
  149. }
  150. $this->response = $client->get($fullUrl, $options);
  151. $this->theHTTPStatusCodeShouldBe(200);
  152. $contents = $this->response->getBody()->getContents();
  153. return json_decode(json_encode(simplexml_load_string($contents)->data), true);
  154. }
  155. /**
  156. * @Given /^user statuses for "([^"]*)" list "([^"]*)" with status "([^"]*)"$/
  157. * @param string $user
  158. * @param string $statusUser
  159. * @param string $status
  160. */
  161. public function assertStatusesList(string $user, string $statusUser, string $status): void {
  162. $statusList = $this->getStatusList($user);
  163. Assert::assertArrayHasKey('element', $statusList, 'Returned status list empty or broken');
  164. if (array_key_exists('userId', $statusList['element'])) {
  165. // If only one user has a status set, the API returns their status directly
  166. Assert::assertArrayHasKey('status', $statusList['element'], 'Returned status list empty or broken');
  167. $filteredStatusList = [ $statusList['element']['userId'] => $statusList['element']['status'] ];
  168. } else {
  169. // If more than one user have their status set, the API returns an array of their statuses
  170. $filteredStatusList = array_column($statusList['element'], 'status', 'userId');
  171. }
  172. Assert::assertArrayHasKey($statusUser, $filteredStatusList, 'User not listed in statuses: ' . $statusUser);
  173. Assert::assertEquals($status, $filteredStatusList[$statusUser]);
  174. }
  175. /**
  176. * @Given /^user statuses for "([^"]*)" are empty$/
  177. * @param string $user
  178. */
  179. public function assertStatusesEmpty(string $user): void {
  180. $statusList = $this->getStatusList($user);
  181. Assert::assertEmpty($statusList);
  182. }
  183. }