Skip to content

Commit f707400

Browse files
authored
Merge pull request #62776 from nextcloud/fix/59329-welcome-email-config-type
fix(provisioning_api): read newUser.sendEmail as a boolean
2 parents a77adfd + 4735e29 commit f707400

6 files changed

Lines changed: 93 additions & 5 deletions

File tree

apps/provisioning_api/lib/Controller/UsersController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,7 @@ public function addUser(
597597
// Send new user mail only if a mail is set
598598
if ($email !== '') {
599599
$newUser->setSystemEMailAddress($email);
600-
if ($this->config->getAppValue('core', 'newUser.sendEmail', 'yes') === 'yes') {
600+
if ($this->appConfig->getValueBool('core', 'newUser.sendEmail', true)) {
601601
try {
602602
$emailTemplate = $this->newUserMailHelper->generateTemplate($newUser, $generatePasswordResetToken);
603603
$this->newUserMailHelper->sendMail($newUser, $emailTemplate);

apps/provisioning_api/tests/Controller/UsersControllerTest.php

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,67 @@ public function testAddUserSuccessfulGeneratePassword(): void {
734734
));
735735
}
736736

737+
/**
738+
* `newUser.sendEmail` has to be read as a boolean. It is stored as an untyped
739+
* 'yes'/'no' string on instances created before Nextcloud 33 and as a typed
740+
* boolean once the account settings toggle has been used, so comparing it to
741+
* the string 'yes' silently skipped the mail on upgraded instances.
742+
*/
743+
#[\PHPUnit\Framework\Attributes\DataProvider('dataAddUserWelcomeMail')]
744+
public function testAddUserSendsWelcomeMailWhenEnabled(bool $enabled): void {
745+
$this->appConfig
746+
->expects($this->atLeastOnce())
747+
->method('getValueBool')
748+
->with('core', 'newUser.sendEmail', true)
749+
->willReturn($enabled);
750+
751+
$newUser = $this->createMock(IUser::class);
752+
$newUser->expects($this->once())
753+
->method('setSystemEMailAddress')
754+
->with('foo@bar.com');
755+
$this->userManager
756+
->expects($this->once())
757+
->method('userExists')
758+
->with('NewUser')
759+
->willReturn(false);
760+
$this->userManager
761+
->expects($this->once())
762+
->method('createUser')
763+
->willReturn($newUser);
764+
$loggedInUser = $this->createMock(IUser::class);
765+
$loggedInUser
766+
->method('getUID')
767+
->willReturn('adminUser');
768+
$this->userSession
769+
->expects($this->once())
770+
->method('getUser')
771+
->willReturn($loggedInUser);
772+
$this->groupManager
773+
->expects($this->once())
774+
->method('isAdmin')
775+
->with('adminUser')
776+
->willReturn(true);
777+
778+
$emailTemplate = $this->createMock(IEMailTemplate::class);
779+
$this->newUserMailHelper
780+
->expects($enabled ? $this->once() : $this->never())
781+
->method('generateTemplate')
782+
->willReturn($emailTemplate);
783+
$this->newUserMailHelper
784+
->expects($enabled ? $this->once() : $this->never())
785+
->method('sendMail')
786+
->with($newUser, $emailTemplate);
787+
788+
$this->api->addUser('NewUser', 'PasswordOfTheNewUser', '', 'foo@bar.com');
789+
}
790+
791+
public static function dataAddUserWelcomeMail(): array {
792+
return [
793+
'enabled' => [true],
794+
'disabled' => [false],
795+
];
796+
}
797+
737798
public function testAddUserSuccessfulLowercaseEmail(): void {
738799
$this->userManager
739800
->expects($this->once())

build/psalm-baseline.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2272,7 +2272,6 @@
22722272
<code><![CDATA[generate]]></code>
22732273
<code><![CDATA[getAppValue]]></code>
22742274
<code><![CDATA[getAppValue]]></code>
2275-
<code><![CDATA[getAppValue]]></code>
22762275
<code><![CDATA[getUserValue]]></code>
22772276
<code><![CDATA[implementsActions]]></code>
22782277
<code><![CDATA[implementsActions]]></code>

core/Command/User/Add.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
183183

184184
$user->setSystemEMailAddress($email);
185185

186-
if ($this->appConfig->getValueString('core', 'newUser.sendEmail', 'yes') === 'yes') {
186+
if ($this->appConfig->getValueBool('core', 'newUser.sendEmail', true)) {
187187
try {
188188
$this->mailHelper->sendMail($user, $this->mailHelper->generateTemplate($user, true));
189189
$output->writeln('Welcome email sent to ' . $email);

tests/Core/Command/User/AddTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,8 @@ public function testAddEmail(
100100
$this->userManager->method('createUser')
101101
->willReturn($this->user);
102102

103-
$this->appConfig->method('getValueString')
104-
->willReturn($shouldSendEmail ? 'yes' : 'no');
103+
$this->appConfig->method('getValueBool')
104+
->willReturn($shouldSendEmail);
105105

106106
$this->mailHelper->method('generateTemplate')
107107
->willReturn(static::createMock(IEMailTemplate::class));

tests/lib/AppConfigIntegrationTest.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,34 @@ public function testGetValueBool(): void {
494494
$this->assertSame(true, $config->getValueBool('typed', 'bool'));
495495
}
496496

497+
/**
498+
* Untyped values predate the typed config API and are still in the database of
499+
* every upgraded instance, so they have to keep resolving to a boolean. The
500+
* deprecated setter is used on purpose, as it is the only way to write a value
501+
* without a type.
502+
*/
503+
#[\PHPUnit\Framework\Attributes\DataProvider('dataUntypedBool')]
504+
public function testGetValueBoolOnUntypedValue(string $stored, bool $expected): void {
505+
/** @var AppConfig $config */
506+
$config = $this->generateAppConfig();
507+
$config->setValue('feed', 'untyped-bool', $stored);
508+
509+
$this->assertSame($expected, $config->getValueBool('feed', 'untyped-bool'));
510+
}
511+
512+
public static function dataUntypedBool(): array {
513+
return [
514+
'yes' => ['yes', true],
515+
'no' => ['no', false],
516+
'true' => ['true', true],
517+
'false' => ['false', false],
518+
'on' => ['on', true],
519+
'1' => ['1', true],
520+
'0' => ['0', false],
521+
'empty' => ['', false],
522+
];
523+
}
524+
497525
public function testGetValueBoolOnUnknownAppReturnsDefault(): void {
498526
$config = $this->generateAppConfig();
499527
$this->assertSame(false, $config->getValueBool('typed-1', 'bool', false));

0 commit comments

Comments
 (0)