MemoryCacheBackendTest.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
  5. * SPDX-License-Identifier: AGPL-3.0-or-later
  6. */
  7. namespace Test\Security\Bruteforce\Backend;
  8. use OC\Security\Bruteforce\Backend\IBackend;
  9. use OC\Security\Bruteforce\Backend\MemoryCacheBackend;
  10. use OCP\AppFramework\Utility\ITimeFactory;
  11. use OCP\ICache;
  12. use OCP\ICacheFactory;
  13. use PHPUnit\Framework\MockObject\MockObject;
  14. use Test\TestCase;
  15. class MemoryCacheBackendTest extends TestCase {
  16. /** @var ICacheFactory|MockObject */
  17. private $cacheFactory;
  18. /** @var ITimeFactory|MockObject */
  19. private $timeFactory;
  20. /** @var ICache|MockObject */
  21. private $cache;
  22. private IBackend $backend;
  23. protected function setUp(): void {
  24. parent::setUp();
  25. $this->cacheFactory = $this->createMock(ICacheFactory::class);
  26. $this->timeFactory = $this->createMock(ITimeFactory::class);
  27. $this->cache = $this->createMock(ICache::class);
  28. $this->cacheFactory
  29. ->expects($this->once())
  30. ->method('createDistributed')
  31. ->with('OC\Security\Bruteforce\Backend\MemoryCacheBackend')
  32. ->willReturn($this->cache);
  33. $this->backend = new MemoryCacheBackend(
  34. $this->cacheFactory,
  35. $this->timeFactory
  36. );
  37. }
  38. public function testGetAttemptsWithNoAttemptsBefore(): void {
  39. $this->cache
  40. ->expects($this->once())
  41. ->method('get')
  42. ->with('8b9da631d1f7b022bb2c3c489e16092f82b42fd4')
  43. ->willReturn(null);
  44. $this->assertSame(0, $this->backend->getAttempts('10.10.10.10/32', 0));
  45. }
  46. public function dataGetAttempts(): array {
  47. return [
  48. [0, null, null, 4],
  49. [100, null, null, 2],
  50. [0, 'action1', null, 2],
  51. [100, 'action1', null, 1],
  52. [0, 'action1', ['metadata2'], 1],
  53. [100, 'action1', ['metadata2'], 1],
  54. [100, 'action1', ['metadata1'], 0],
  55. ];
  56. }
  57. /**
  58. * @dataProvider dataGetAttempts
  59. */
  60. public function testGetAttempts(int $maxAge, ?string $action, ?array $metadata, int $expected): void {
  61. $this->cache
  62. ->expects($this->once())
  63. ->method('get')
  64. ->with('8b9da631d1f7b022bb2c3c489e16092f82b42fd4')
  65. ->willReturn(json_encode([
  66. '1' . '#' . hash('sha1', 'action1') . '#' . hash('sha1', json_encode(['metadata1'])),
  67. '300' . '#' . hash('sha1', 'action1') . '#' . hash('sha1', json_encode(['metadata2'])),
  68. '1' . '#' . hash('sha1', 'action2') . '#' . hash('sha1', json_encode(['metadata1'])),
  69. '300' . '#' . hash('sha1', 'action2') . '#' . hash('sha1', json_encode(['metadata2'])),
  70. ]));
  71. $this->assertSame($expected, $this->backend->getAttempts('10.10.10.10/32', $maxAge, $action, $metadata));
  72. }
  73. public function testRegisterAttemptWithNoAttemptsBefore(): void {
  74. $this->cache
  75. ->expects($this->once())
  76. ->method('get')
  77. ->with('8b9da631d1f7b022bb2c3c489e16092f82b42fd4')
  78. ->willReturn(null);
  79. $this->cache
  80. ->expects($this->once())
  81. ->method('set')
  82. ->with(
  83. '8b9da631d1f7b022bb2c3c489e16092f82b42fd4',
  84. json_encode(['223#' . hash('sha1', 'action1') . '#' . hash('sha1', json_encode(['metadata1']))])
  85. );
  86. $this->backend->registerAttempt('10.10.10.10', '10.10.10.10/32', 223, 'action1', ['metadata1']);
  87. }
  88. public function testRegisterAttempt(): void {
  89. $this->timeFactory
  90. ->expects($this->once())
  91. ->method('getTime')
  92. ->willReturn(12 * 3600 + 86);
  93. $this->cache
  94. ->expects($this->once())
  95. ->method('get')
  96. ->with('8b9da631d1f7b022bb2c3c489e16092f82b42fd4')
  97. ->willReturn(json_encode([
  98. '1#' . hash('sha1', 'action1') . '#' . hash('sha1', json_encode(['metadata1'])),
  99. '2#' . hash('sha1', 'action2') . '#' . hash('sha1', json_encode(['metadata1'])),
  100. '87#' . hash('sha1', 'action3') . '#' . hash('sha1', json_encode(['metadata1'])),
  101. '123#' . hash('sha1', 'action4') . '#' . hash('sha1', json_encode(['metadata1'])),
  102. '123#' . hash('sha1', 'action5') . '#' . hash('sha1', json_encode(['metadata1'])),
  103. '124#' . hash('sha1', 'action6') . '#' . hash('sha1', json_encode(['metadata1'])),
  104. ]));
  105. $this->cache
  106. ->expects($this->once())
  107. ->method('set')
  108. ->with(
  109. '8b9da631d1f7b022bb2c3c489e16092f82b42fd4',
  110. json_encode([
  111. '87#' . hash('sha1', 'action3') . '#' . hash('sha1', json_encode(['metadata1'])),
  112. '123#' . hash('sha1', 'action4') . '#' . hash('sha1', json_encode(['metadata1'])),
  113. '123#' . hash('sha1', 'action5') . '#' . hash('sha1', json_encode(['metadata1'])),
  114. '124#' . hash('sha1', 'action6') . '#' . hash('sha1', json_encode(['metadata1'])),
  115. '186#' . hash('sha1', 'action7') . '#' . hash('sha1', json_encode(['metadata2'])),
  116. ])
  117. );
  118. $this->backend->registerAttempt('10.10.10.10', '10.10.10.10/32', 186, 'action7', ['metadata2']);
  119. }
  120. }