Skip to content

Commit 1d74130

Browse files
committed
Fair use of push notifications
We want to keep offering our push notification service for free, but large users overload our infrastructure. For this reason we have to rate-limit the use of push notifications. If you need this feature, consider setting up your own push server or using Nextcloud Enterprise. Signed-off-by: Joas Schilling <[email protected]>
1 parent 519c37c commit 1d74130

3 files changed

Lines changed: 101 additions & 0 deletions

File tree

lib/Command/TestPush.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,14 @@ protected function configure(): void {
8585
* @return int
8686
*/
8787
protected function execute(InputInterface $input, OutputInterface $output): int {
88+
if (!$this->notificationManager->isFairUseOfFreePushService()) {
89+
$output->writeln('<error>We want to keep offering our push notification service for free, but large</error>');
90+
$output->writeln('<error>users overload our infrastructure. For this reason we have to rate-limit the</error>');
91+
$output->writeln('<error>use of push notifications. If you need this feature, consider setting up your</error>');
92+
$output->writeln('<error>own push server or using Nextcloud Enterprise.</error>');
93+
return 1;
94+
}
95+
8896
$userId = $input->getArgument('user-id');
8997
$subject = 'Testing push notifications';
9098

lib/Push.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,16 @@ protected function sendNotificationsToProxies(): void {
295295
return;
296296
}
297297

298+
if (!$this->notificationManager->isFairUseOfFreePushService()) {
299+
/**
300+
* We want to keep offering our push notification service for free, but large
301+
* users overload our infrastructure. For this reason we have to rate-limit the
302+
* use of push notifications. If you need this feature, consider setting up your
303+
* own push server or using Nextcloud Enterprise.
304+
*/
305+
return;
306+
}
307+
298308
$client = $this->clientService->newClient();
299309
foreach ($pushNotifications as $proxyServer => $notifications) {
300310
try {

tests/Unit/PushTest.php

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,83 @@ public function testPushToDeviceEncryptionError() {
394394

395395
$push->pushToDevice(1970, $notification);
396396
}
397+
public function testPushToDeviceNoFairUse() {
398+
$push = $this->getPush(['getDevicesForUser', 'encryptAndSign', 'deletePushToken', 'validateToken', 'deletePushTokenByDeviceIdentifier']);
399+
400+
/** @var INotification|MockObject $notification */
401+
$notification = $this->createMock(INotification::class);
402+
$notification
403+
->method('getUser')
404+
->willReturn('valid');
405+
406+
/** @var IUser|MockObject $user */
407+
$user = $this->createMock(IUser::class);
408+
409+
$this->userManager->expects($this->once())
410+
->method('get')
411+
->with('valid')
412+
->willReturn($user);
413+
414+
$push->expects($this->once())
415+
->method('getDevicesForUser')
416+
->willReturn([
417+
[
418+
'proxyserver' => 'proxyserver',
419+
'token' => 16,
420+
'apptype' => 'other',
421+
],
422+
]);
423+
424+
$this->config
425+
->method('getSystemValue')
426+
->with('debug', false)
427+
->willReturn(false);
428+
429+
$this->l10nFactory
430+
->method('getUserLanguage')
431+
->with($user)
432+
->willReturn('ru');
433+
434+
$this->notificationManager->expects($this->once())
435+
->method('prepare')
436+
->with($notification, 'ru')
437+
->willReturnArgument(0);
438+
439+
/** @var Key|MockObject $key */
440+
$key = $this->createMock(Key::class);
441+
442+
$this->keyManager->expects($this->once())
443+
->method('getKey')
444+
->with($user)
445+
->willReturn($key);
446+
447+
$push->expects($this->exactly(1))
448+
->method('validateToken')
449+
->willReturn(true);
450+
451+
$push->expects($this->exactly(1))
452+
->method('encryptAndSign')
453+
->willReturn(['Payload']);
454+
455+
$push->expects($this->never())
456+
->method('deletePushToken');
457+
458+
$this->clientService->expects($this->never())
459+
->method('newClient');
460+
461+
$this->config->expects($this->once())
462+
->method('getSystemValueBool')
463+
->with('has_internet_connection', true)
464+
->willReturn(true);
465+
466+
$this->notificationManager->method('isFairUseOfFreePushService')
467+
->willReturn(false);
468+
469+
$push->method('deletePushTokenByDeviceIdentifier')
470+
->with('123456');
471+
472+
$push->pushToDevice(207787, $notification);
473+
}
397474

398475
public function dataPushToDeviceSending() {
399476
return [
@@ -631,6 +708,9 @@ public function testPushToDeviceSending($isDebug) {
631708
])
632709
->willThrowException($e);
633710

711+
$this->notificationManager->method('isFairUseOfFreePushService')
712+
->willReturn(true);
713+
634714
$push->method('deletePushTokenByDeviceIdentifier')
635715
->with('123456');
636716

@@ -762,6 +842,9 @@ public function testPushToDeviceTalkNotification(array $deviceTypes, $isTalkNoti
762842
->with('has_internet_connection', true)
763843
->willReturn(true);
764844

845+
$this->notificationManager->method('isFairUseOfFreePushService')
846+
->willReturn(true);
847+
765848
$push->pushToDevice(200718, $notification);
766849
}
767850
}

0 commit comments

Comments
 (0)