Skip to content

Commit f89549c

Browse files
authored
Merge pull request #2562 from nextcloud/fix/bulk-receive-email-notification-bypass
fix(bulkReceive): honour admin email toggle and ISetting notification defaults
2 parents 29d896c + 4e3129f commit f89549c

2 files changed

Lines changed: 71 additions & 15 deletions

File tree

lib/Consumer.php

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use OCP\Config\IUserConfig;
1717
use OCP\Config\ValueType;
1818
use OCP\DB\Exception;
19+
use OCP\IAppConfig;
1920

2021
class Consumer implements IConsumer, IBulkConsumer {
2122

@@ -25,6 +26,7 @@ public function __construct(
2526
protected UserSettings $userSettings,
2627
protected NotificationGenerator $notificationGenerator,
2728
protected IUserConfig $userConfig,
29+
protected IAppConfig $appConfig,
2830
) {
2931
}
3032

@@ -78,13 +80,16 @@ public function bulkReceive(IEvent $event, array $affectedUserIds, ISetting $set
7880

7981
$canChangeMail = $setting->canChangeMail();
8082
$canChangePush = $setting instanceof ActivitySettings && $setting->canChangeNotification() === true;
83+
$defaultPushEnabled = $setting instanceof ActivitySettings && $setting->isDefaultEnabledNotification();
8184

82-
$userPushSettings = $userEmailSettings = $batchTimeSettings = null;
85+
$userPushSettings = null;
8386
if ($canChangePush === true) {
8487
$userPushSettings = $this->userConfig->getValuesByUsers('activity', 'notify_notification_' . $event->getType(), ValueType::BOOL, $affectedUserIds);
8588
}
8689

87-
if ($canChangeMail === true || $setting->isDefaultEnabledMail() === true) {
90+
$userEmailSettings = $batchTimeSettings = null;
91+
$emailEnabled = $this->appConfig->getValueString('activity', 'enable_email', 'yes') !== 'no';
92+
if ($emailEnabled && ($canChangeMail === true || $setting->isDefaultEnabledMail() === true)) {
8893
$userEmailSettings = $this->userConfig->getValuesByUsers('activity', 'notify_email_' . $event->getType(), ValueType::BOOL, $affectedUserIds);
8994
$batchTimeSettings = $this->userConfig->getValuesByUsers('activity', 'notify_setting_batchtime', ValueType::INT, $affectedUserIds);
9095
}
@@ -95,14 +100,17 @@ public function bulkReceive(IEvent $event, array $affectedUserIds, ISetting $set
95100
continue;
96101
}
97102
$event->setAffectedUser($affectedUser);
98-
$notificationSetting = $userPushSettings[$affectedUser] ?? null;
99-
if ($notificationSetting !== null) {
100-
$notificationSetting = (bool)$notificationSetting;
103+
104+
if ($canChangePush === true) {
105+
$notificationSetting = isset($userPushSettings[$affectedUser]) ? (bool)$userPushSettings[$affectedUser] : $defaultPushEnabled;
106+
} else {
107+
$notificationSetting = $defaultPushEnabled;
101108
}
109+
102110
$emailSetting = $userEmailSettings[$affectedUser] ?? false;
103111
$emailSetting = ($emailSetting) ? ($batchTimeSettings[$affectedUser] ?? false) : false;
104112

105-
if ($notificationSetting !== false) {
113+
if ($notificationSetting === true) {
106114
$this->notificationGenerator->sendNotificationForEvent($event, $activityId, $notificationSetting);
107115
}
108116

tests/ConsumerTest.php

Lines changed: 57 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
use OCP\Activity\IManager;
3434
use OCP\Activity\ISetting;
3535
use OCP\Config\IUserConfig;
36+
use OCP\IAppConfig;
3637
use OCP\IDBConnection;
3738
use OCP\IL10N;
3839
use OCP\L10N\IFactory;
@@ -53,6 +54,7 @@ class ConsumerTest extends TestCase {
5354
protected NotificationGenerator&MockObject $notificationGenerator;
5455
protected UserSettings $userSettings;
5556
private IUserConfig&MockObject $userConfig;
57+
private IAppConfig&MockObject $appConfig;
5658
private IEvent $event;
5759
private Consumer $consumer;
5860

@@ -70,7 +72,10 @@ protected function setUp(): void {
7072
$this->notificationGenerator = $this->createMock(NotificationGenerator::class);
7173
$this->l10nFactory = $this->createMock(IFactory::class);
7274
$this->userConfig = $this->createMock(IUserConfig::class);
73-
75+
$this->appConfig = $this->createMock(IAppConfig::class);
76+
$this->appConfig->method('getValueString')
77+
->with('activity', 'enable_email', 'yes')
78+
->willReturn('yes');
7479
$this->data->method('send')
7580
->willReturn(1);
7681
$this->l10nFactory
@@ -95,6 +100,7 @@ protected function setUp(): void {
95100
$this->userSettings,
96101
$this->notificationGenerator,
97102
$this->userConfig,
103+
$this->appConfig,
98104
);
99105

100106
$this->event = Server::get(IManager::class)->generateEvent();
@@ -143,6 +149,7 @@ public function testReceiveStream(string $type, string $author, string $affected
143149
$this->userSettings,
144150
$this->notificationGenerator,
145151
$this->userConfig,
152+
$this->appConfig,
146153
);
147154
$event = Server::get(IManager::class)->generateEvent();
148155
$event->setApp('test')
@@ -322,9 +329,7 @@ public function testBulkReceiveNoMailWhenSettingDisabled(): void {
322329

323330
$this->data->expects($this->never())
324331
->method('storeMail');
325-
// Notification is still sent because $notificationSetting defaults to null
326-
// and null !== false, so the default is to send notifications
327-
$this->notificationGenerator->expects($this->once())
332+
$this->notificationGenerator->expects($this->never())
328333
->method('sendNotificationForEvent');
329334

330335
$this->consumer->bulkReceive($this->event, ['affectedUser'], $settings);
@@ -434,8 +439,8 @@ public function testBulkReceiveMultipleUsersWithMixedSettings(): void {
434439
return [];
435440
});
436441

437-
// user1 and user2 get notifications (user2 has null setting which defaults to send), author is skipped
438-
$this->notificationGenerator->expects($this->exactly(2))
442+
// only user1 has an explicit notification=true in DB; user2 has no entry so falls back to isDefaultEnabledNotification()=false
443+
$this->notificationGenerator->expects($this->once())
439444
->method('sendNotificationForEvent');
440445
// user2 gets email, author is skipped
441446
$this->data->expects($this->once())
@@ -445,6 +450,50 @@ public function testBulkReceiveMultipleUsersWithMixedSettings(): void {
445450
$this->consumer->bulkReceive($this->event, ['user1', 'user2', 'author'], $settings);
446451
}
447452

453+
public function testBulkReceiveNoMailWhenAdminEmailDisabled(): void {
454+
$time = time();
455+
$this->event->setApp('activity')
456+
->setType('type')
457+
->setAuthor('author')
458+
->setTimestamp($time)
459+
->setSubject('subject', ['subjectParam1'])
460+
->setMessage('message', ['messageParam1'])
461+
->setObject('', 0, 'file')
462+
->setLink('link');
463+
464+
$appConfig = $this->createMock(IAppConfig::class);
465+
$appConfig->method('getValueString')
466+
->with('activity', 'enable_email', 'yes')
467+
->willReturn('no');
468+
469+
$consumer = new Consumer(
470+
$this->data,
471+
$this->activityManager,
472+
$this->userSettings,
473+
$this->notificationGenerator,
474+
$this->userConfig,
475+
$appConfig,
476+
);
477+
478+
$settings = $this->createMock(ActivitySettings::class);
479+
$settings->method('canChangeMail')->willReturn(true);
480+
$settings->method('isDefaultEnabledMail')->willReturn(true);
481+
$settings->method('canChangeNotification')->willReturn(false);
482+
$settings->method('isDefaultEnabledNotification')->willReturn(false);
483+
484+
$this->data->expects($this->once())
485+
->method('bulkSend')
486+
->willReturn([1 => 'affectedUser']);
487+
488+
$this->userConfig->expects($this->never())
489+
->method('getValuesByUsers');
490+
491+
$this->data->expects($this->never())
492+
->method('storeMail');
493+
494+
$consumer->bulkReceive($this->event, ['affectedUser'], $settings);
495+
}
496+
448497
public function testBulkReceiveWithISetting(): void {
449498
$this->event->setApp('activity')
450499
->setType('type')
@@ -463,9 +512,8 @@ public function testBulkReceiveWithISetting(): void {
463512
->method('bulkSend')
464513
->willReturn([1 => 'affectedUser']);
465514

466-
// Notification is still sent because $notificationSetting defaults to null (not false)
467-
// when ISetting is used (canChangeNotification not available), and null !== false
468-
$this->notificationGenerator->expects($this->once())
515+
// ISetting is not ActivitySettings so $defaultPushEnabled is false — no notification sent
516+
$this->notificationGenerator->expects($this->never())
469517
->method('sendNotificationForEvent');
470518
$this->data->expects($this->never())
471519
->method('storeMail');

0 commit comments

Comments
 (0)