TrustedServersTest.php 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
  5. * SPDX-License-Identifier: AGPL-3.0-only
  6. */
  7. namespace OCA\Federation\Tests;
  8. use OCA\Federation\DbHandler;
  9. use OCA\Federation\TrustedServers;
  10. use OCP\AppFramework\Utility\ITimeFactory;
  11. use OCP\BackgroundJob\IJobList;
  12. use OCP\EventDispatcher\IEventDispatcher;
  13. use OCP\Http\Client\IClient;
  14. use OCP\Http\Client\IClientService;
  15. use OCP\Http\Client\IResponse;
  16. use OCP\IConfig;
  17. use OCP\Security\ISecureRandom;
  18. use Psr\Log\LoggerInterface;
  19. use Test\TestCase;
  20. class TrustedServersTest extends TestCase {
  21. /** @var \PHPUnit\Framework\MockObject\MockObject | TrustedServers */
  22. private $trustedServers;
  23. /** @var \PHPUnit\Framework\MockObject\MockObject | DbHandler */
  24. private $dbHandler;
  25. /** @var \PHPUnit\Framework\MockObject\MockObject | IClientService */
  26. private $httpClientService;
  27. /** @var \PHPUnit\Framework\MockObject\MockObject | IClient */
  28. private $httpClient;
  29. /** @var \PHPUnit\Framework\MockObject\MockObject | IResponse */
  30. private $response;
  31. /** @var \PHPUnit\Framework\MockObject\MockObject | LoggerInterface */
  32. private $logger;
  33. /** @var \PHPUnit\Framework\MockObject\MockObject | IJobList */
  34. private $jobList;
  35. /** @var \PHPUnit\Framework\MockObject\MockObject | ISecureRandom */
  36. private $secureRandom;
  37. /** @var \PHPUnit\Framework\MockObject\MockObject | IConfig */
  38. private $config;
  39. /** @var \PHPUnit\Framework\MockObject\MockObject | IEventDispatcher */
  40. private $dispatcher;
  41. /** @var \PHPUnit\Framework\MockObject\MockObject|ITimeFactory */
  42. private $timeFactory;
  43. protected function setUp(): void {
  44. parent::setUp();
  45. $this->dbHandler = $this->getMockBuilder(DbHandler::class)
  46. ->disableOriginalConstructor()->getMock();
  47. $this->dispatcher = $this->getMockBuilder(IEventDispatcher::class)
  48. ->disableOriginalConstructor()->getMock();
  49. $this->httpClientService = $this->getMockBuilder(IClientService::class)->getMock();
  50. $this->httpClient = $this->getMockBuilder(IClient::class)->getMock();
  51. $this->response = $this->getMockBuilder(IResponse::class)->getMock();
  52. $this->logger = $this->getMockBuilder(LoggerInterface::class)->getMock();
  53. $this->jobList = $this->getMockBuilder(IJobList::class)->getMock();
  54. $this->secureRandom = $this->getMockBuilder(ISecureRandom::class)->getMock();
  55. $this->config = $this->getMockBuilder(IConfig::class)->getMock();
  56. $this->timeFactory = $this->createMock(ITimeFactory::class);
  57. $this->trustedServers = new TrustedServers(
  58. $this->dbHandler,
  59. $this->httpClientService,
  60. $this->logger,
  61. $this->jobList,
  62. $this->secureRandom,
  63. $this->config,
  64. $this->dispatcher,
  65. $this->timeFactory
  66. );
  67. }
  68. public function testAddServer(): void {
  69. /** @var \PHPUnit\Framework\MockObject\MockObject|TrustedServers $trustedServers */
  70. $trustedServers = $this->getMockBuilder('OCA\Federation\TrustedServers')
  71. ->setConstructorArgs(
  72. [
  73. $this->dbHandler,
  74. $this->httpClientService,
  75. $this->logger,
  76. $this->jobList,
  77. $this->secureRandom,
  78. $this->config,
  79. $this->dispatcher,
  80. $this->timeFactory
  81. ]
  82. )
  83. ->setMethods(['normalizeUrl', 'updateProtocol'])
  84. ->getMock();
  85. $trustedServers->expects($this->once())->method('updateProtocol')
  86. ->with('url')->willReturn('https://url');
  87. $this->timeFactory->method('getTime')
  88. ->willReturn(1234567);
  89. $this->dbHandler->expects($this->once())->method('addServer')->with('https://url')
  90. ->willReturn(1);
  91. $this->secureRandom->expects($this->once())->method('generate')
  92. ->willReturn('token');
  93. $this->dbHandler->expects($this->once())->method('addToken')->with('https://url', 'token');
  94. $this->jobList->expects($this->once())->method('add')
  95. ->with('OCA\Federation\BackgroundJob\RequestSharedSecret',
  96. ['url' => 'https://url', 'token' => 'token', 'created' => 1234567]);
  97. $this->assertSame(
  98. $trustedServers->addServer('url'),
  99. 1
  100. );
  101. }
  102. public function testAddSharedSecret(): void {
  103. $this->dbHandler->expects($this->once())->method('addSharedSecret')
  104. ->with('url', 'secret');
  105. $this->trustedServers->addSharedSecret('url', 'secret');
  106. }
  107. public function testGetSharedSecret(): void {
  108. $this->dbHandler->expects($this->once())
  109. ->method('getSharedSecret')
  110. ->with('url')
  111. ->willReturn('secret');
  112. $this->assertSame(
  113. $this->trustedServers->getSharedSecret('url'),
  114. 'secret'
  115. );
  116. }
  117. public function testRemoveServer(): void {
  118. $id = 42;
  119. $server = ['url_hash' => 'url_hash'];
  120. $this->dbHandler->expects($this->once())->method('removeServer')->with($id);
  121. $this->dbHandler->expects($this->once())->method('getServerById')->with($id)
  122. ->willReturn($server);
  123. $this->dispatcher->expects($this->once())->method('dispatchTyped')
  124. ->willReturnCallback(
  125. function ($event) {
  126. $this->assertSame(get_class($event), \OCP\Federation\Events\TrustedServerRemovedEvent::class);
  127. /** @var \OCP\Federated\Events\TrustedServerRemovedEvent $event */
  128. $this->assertSame('url_hash', $event->getUrlHash());
  129. }
  130. );
  131. $this->trustedServers->removeServer($id);
  132. }
  133. public function testGetServers(): void {
  134. $this->dbHandler->expects($this->once())->method('getAllServer')->willReturn(['servers']);
  135. $this->assertEquals(
  136. ['servers'],
  137. $this->trustedServers->getServers()
  138. );
  139. }
  140. public function testIsTrustedServer(): void {
  141. $this->dbHandler->expects($this->once())
  142. ->method('serverExists')->with('url')
  143. ->willReturn(true);
  144. $this->assertTrue(
  145. $this->trustedServers->isTrustedServer('url')
  146. );
  147. }
  148. public function testSetServerStatus(): void {
  149. $this->dbHandler->expects($this->once())->method('setServerStatus')
  150. ->with('url', 1);
  151. $this->trustedServers->setServerStatus('url', 1);
  152. }
  153. public function testGetServerStatus(): void {
  154. $this->dbHandler->expects($this->once())->method('getServerStatus')
  155. ->with('url')->willReturn(1);
  156. $this->assertSame(
  157. $this->trustedServers->getServerStatus('url'),
  158. 1
  159. );
  160. }
  161. /**
  162. * @dataProvider dataTestIsNextcloudServer
  163. */
  164. public function testIsNextcloudServer(int $statusCode, bool $isValidNextcloudVersion, bool $expected): void {
  165. $server = 'server1';
  166. /** @var \PHPUnit\Framework\MockObject\MockObject | TrustedServers $trustedServers */
  167. $trustedServers = $this->getMockBuilder('OCA\Federation\TrustedServers')
  168. ->setConstructorArgs(
  169. [
  170. $this->dbHandler,
  171. $this->httpClientService,
  172. $this->logger,
  173. $this->jobList,
  174. $this->secureRandom,
  175. $this->config,
  176. $this->dispatcher,
  177. $this->timeFactory
  178. ]
  179. )
  180. ->setMethods(['checkNextcloudVersion'])
  181. ->getMock();
  182. $this->httpClientService->expects($this->once())->method('newClient')
  183. ->willReturn($this->httpClient);
  184. $this->httpClient->expects($this->once())->method('get')->with($server . '/status.php')
  185. ->willReturn($this->response);
  186. $this->response->expects($this->once())->method('getStatusCode')
  187. ->willReturn($statusCode);
  188. if ($statusCode === 200) {
  189. $this->response->expects($this->once())->method('getBody')
  190. ->willReturn('');
  191. $trustedServers->expects($this->once())->method('checkNextcloudVersion')
  192. ->willReturn($isValidNextcloudVersion);
  193. } else {
  194. $trustedServers->expects($this->never())->method('checkNextcloudVersion');
  195. }
  196. $this->assertSame($expected,
  197. $trustedServers->isNextcloudServer($server)
  198. );
  199. }
  200. public function dataTestIsNextcloudServer(): array {
  201. return [
  202. [200, true, true],
  203. [200, false, false],
  204. [404, true, false],
  205. ];
  206. }
  207. /**
  208. * @expectedExceptionMessage simulated exception
  209. */
  210. public function testIsNextcloudServerFail(): void {
  211. $server = 'server1';
  212. $this->httpClientService->expects($this->once())->method('newClient')
  213. ->willReturn($this->httpClient);
  214. $this->httpClient->expects($this->once())->method('get')->with($server . '/status.php')
  215. ->willReturnCallback(function () {
  216. throw new \Exception('simulated exception');
  217. });
  218. $this->assertFalse($this->trustedServers->isNextcloudServer($server));
  219. }
  220. /**
  221. * @dataProvider dataTestCheckNextcloudVersion
  222. */
  223. public function testCheckNextcloudVersion($status): void {
  224. $this->assertTrue($this->invokePrivate($this->trustedServers, 'checkNextcloudVersion', [$status]));
  225. }
  226. public function dataTestCheckNextcloudVersion(): array {
  227. return [
  228. ['{"version":"9.0.0"}'],
  229. ['{"version":"9.1.0"}']
  230. ];
  231. }
  232. /**
  233. * @dataProvider dataTestCheckNextcloudVersionTooLow
  234. */
  235. public function testCheckNextcloudVersionTooLow(string $status): void {
  236. $this->expectException(\OCP\HintException::class);
  237. $this->expectExceptionMessage('Remote server version is too low. 9.0 is required.');
  238. $this->invokePrivate($this->trustedServers, 'checkNextcloudVersion', [$status]);
  239. }
  240. public function dataTestCheckNextcloudVersionTooLow(): array {
  241. return [
  242. ['{"version":"8.2.3"}'],
  243. ];
  244. }
  245. /**
  246. * @dataProvider dataTestUpdateProtocol
  247. */
  248. public function testUpdateProtocol(string $url, string $expected): void {
  249. $this->assertSame($expected,
  250. $this->invokePrivate($this->trustedServers, 'updateProtocol', [$url])
  251. );
  252. }
  253. public function dataTestUpdateProtocol(): array {
  254. return [
  255. ['http://owncloud.org', 'http://owncloud.org'],
  256. ['https://owncloud.org', 'https://owncloud.org'],
  257. ['owncloud.org', 'https://owncloud.org'],
  258. ['httpserver', 'https://httpserver'],
  259. ];
  260. }
  261. }