TrustedServersTest.php 9.2 KB

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