RateLimitingPluginTest.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4. * @copyright 2023 Christoph Wurst <christoph@winzerhof-wurst.at>
  5. *
  6. * @author 2023 Christoph Wurst <christoph@winzerhof-wurst.at>
  7. *
  8. * @license GNU AGPL version 3 or any later version
  9. *
  10. * This program is free software: you can redistribute it and/or modify
  11. * it under the terms of the GNU Affero General Public License as
  12. * published by the Free Software Foundation, either version 3 of the
  13. * License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU Affero General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Affero General Public License
  21. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. */
  23. namespace OCA\DAV\Tests\unit\CalDAV\Security;
  24. use OC\Security\RateLimiting\Exception\RateLimitExceededException;
  25. use OC\Security\RateLimiting\Limiter;
  26. use OCA\DAV\CalDAV\CalDavBackend;
  27. use OCA\DAV\CalDAV\Security\RateLimitingPlugin;
  28. use OCA\DAV\Connector\Sabre\Exception\TooManyRequests;
  29. use OCP\IAppConfig;
  30. use OCP\IUser;
  31. use OCP\IUserManager;
  32. use PHPUnit\Framework\MockObject\MockObject;
  33. use Psr\Log\LoggerInterface;
  34. use Sabre\DAV\Exception\Forbidden;
  35. use Test\TestCase;
  36. class RateLimitingPluginTest extends TestCase {
  37. private Limiter|MockObject $limiter;
  38. private CalDavBackend|MockObject $caldavBackend;
  39. private IUserManager|MockObject $userManager;
  40. private LoggerInterface|MockObject $logger;
  41. private IAppConfig|MockObject $config;
  42. private string $userId = 'user123';
  43. private RateLimitingPlugin $plugin;
  44. protected function setUp(): void {
  45. parent::setUp();
  46. $this->limiter = $this->createMock(Limiter::class);
  47. $this->userManager = $this->createMock(IUserManager::class);
  48. $this->caldavBackend = $this->createMock(CalDavBackend::class);
  49. $this->logger = $this->createMock(LoggerInterface::class);
  50. $this->config = $this->createMock(IAppConfig::class);
  51. $this->plugin = new RateLimitingPlugin(
  52. $this->limiter,
  53. $this->userManager,
  54. $this->caldavBackend,
  55. $this->logger,
  56. $this->config,
  57. $this->userId,
  58. );
  59. }
  60. public function testNoUserObject(): void {
  61. $this->limiter->expects(self::never())
  62. ->method('registerUserRequest');
  63. $this->plugin->beforeBind('calendars/foo/cal');
  64. }
  65. public function testUnrelated(): void {
  66. $user = $this->createMock(IUser::class);
  67. $this->userManager->expects(self::once())
  68. ->method('get')
  69. ->with($this->userId)
  70. ->willReturn($user);
  71. $this->limiter->expects(self::never())
  72. ->method('registerUserRequest');
  73. $this->plugin->beforeBind('foo/bar');
  74. }
  75. public function testRegisterCalendarCreation(): void {
  76. $user = $this->createMock(IUser::class);
  77. $this->userManager->expects(self::once())
  78. ->method('get')
  79. ->with($this->userId)
  80. ->willReturn($user);
  81. $this->config
  82. ->method('getValueInt')
  83. ->with('dav')
  84. ->willReturnArgument(2);
  85. $this->limiter->expects(self::once())
  86. ->method('registerUserRequest')
  87. ->with(
  88. 'caldav-create-calendar',
  89. 10,
  90. 3600,
  91. $user,
  92. );
  93. $this->plugin->beforeBind('calendars/foo/cal');
  94. }
  95. public function testCalendarCreationRateLimitExceeded(): void {
  96. $user = $this->createMock(IUser::class);
  97. $this->userManager->expects(self::once())
  98. ->method('get')
  99. ->with($this->userId)
  100. ->willReturn($user);
  101. $this->config
  102. ->method('getValueInt')
  103. ->with('dav')
  104. ->willReturnArgument(2);
  105. $this->limiter->expects(self::once())
  106. ->method('registerUserRequest')
  107. ->with(
  108. 'caldav-create-calendar',
  109. 10,
  110. 3600,
  111. $user,
  112. )
  113. ->willThrowException(new RateLimitExceededException());
  114. $this->expectException(TooManyRequests::class);
  115. $this->plugin->beforeBind('calendars/foo/cal');
  116. }
  117. public function testCalendarLimitReached(): void {
  118. $user = $this->createMock(IUser::class);
  119. $this->userManager->expects(self::once())
  120. ->method('get')
  121. ->with($this->userId)
  122. ->willReturn($user);
  123. $user->method('getUID')->willReturn('user123');
  124. $this->config
  125. ->method('getValueInt')
  126. ->with('dav')
  127. ->willReturnArgument(2);
  128. $this->limiter->expects(self::once())
  129. ->method('registerUserRequest')
  130. ->with(
  131. 'caldav-create-calendar',
  132. 10,
  133. 3600,
  134. $user,
  135. );
  136. $this->caldavBackend->expects(self::once())
  137. ->method('getCalendarsForUserCount')
  138. ->with('principals/users/user123')
  139. ->willReturn(27);
  140. $this->caldavBackend->expects(self::once())
  141. ->method('getSubscriptionsForUserCount')
  142. ->with('principals/users/user123')
  143. ->willReturn(3);
  144. $this->expectException(Forbidden::class);
  145. $this->plugin->beforeBind('calendars/foo/cal');
  146. }
  147. public function testNoCalendarsSubscriptsLimit(): void {
  148. $user = $this->createMock(IUser::class);
  149. $this->userManager->expects(self::once())
  150. ->method('get')
  151. ->with($this->userId)
  152. ->willReturn($user);
  153. $user->method('getUID')->willReturn('user123');
  154. $this->config
  155. ->method('getValueInt')
  156. ->with('dav')
  157. ->willReturnCallback(function ($app, $key, $default) {
  158. switch ($key) {
  159. case 'maximumCalendarsSubscriptions':
  160. return -1;
  161. default:
  162. return $default;
  163. }
  164. });
  165. $this->limiter->expects(self::once())
  166. ->method('registerUserRequest')
  167. ->with(
  168. 'caldav-create-calendar',
  169. 10,
  170. 3600,
  171. $user,
  172. );
  173. $this->caldavBackend->expects(self::never())
  174. ->method('getCalendarsForUserCount')
  175. ->with('principals/users/user123')
  176. ->willReturn(27);
  177. $this->caldavBackend->expects(self::never())
  178. ->method('getSubscriptionsForUserCount')
  179. ->with('principals/users/user123')
  180. ->willReturn(3);
  181. $this->plugin->beforeBind('calendars/foo/cal');
  182. }
  183. }