From 3c7755fc662b0fcedad261e2e12755faedb1c567 Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Wed, 23 Nov 2016 19:50:58 +0100 Subject: [PATCH 1/7] send email to new user with password forgotten link to create own password Signed-off-by: Morris Jobke --- settings/Controller/UsersController.php | 39 ++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/settings/Controller/UsersController.php b/settings/Controller/UsersController.php index 719b6eb68f..f9be5468d3 100644 --- a/settings/Controller/UsersController.php +++ b/settings/Controller/UsersController.php @@ -49,7 +49,9 @@ use OCP\IUserManager; use OCP\IUserSession; use OCP\Mail\IMailer; use OCP\IAvatarManager; -use Punic\Exception; +use OCP\Security\ICrypto; +use OCP\Security\ISecureRandom; +use OC\AppFramework\Utility\TimeFactory; /** * @package OC\Settings\Controller @@ -85,6 +87,13 @@ class UsersController extends Controller { private $avatarManager; /** @var AccountManager */ private $accountManager; + /** @var ISecureRandom */ + private $secureRandom; + /** @var TimeFactory */ + private $timeFactory; + /** @var ICrypto */ + private $crypto; + /** * @param string $appName @@ -103,6 +112,9 @@ class UsersController extends Controller { * @param IAppManager $appManager * @param IAvatarManager $avatarManager * @param AccountManager $accountManager + * @param ISecureRandom $secureRandom + * @param TimeFactory $timeFactory + * @param ICrypto $crypto */ public function __construct($appName, IRequest $request, @@ -119,8 +131,10 @@ class UsersController extends Controller { IURLGenerator $urlGenerator, IAppManager $appManager, IAvatarManager $avatarManager, - AccountManager $accountManager -) { + AccountManager $accountManager, + ISecureRandom $secureRandom, + TimeFactory $timeFactory, + ICrypto $crypto) { parent::__construct($appName, $request); $this->userManager = $userManager; $this->groupManager = $groupManager; @@ -135,6 +149,9 @@ class UsersController extends Controller { $this->urlGenerator = $urlGenerator; $this->avatarManager = $avatarManager; $this->accountManager = $accountManager; + $this->secureRandom = $secureRandom; + $this->timeFactory = $timeFactory; + $this->crypto = $crypto; // check for encryption state - TODO see formatUserForIndex $this->isEncryptionAppEnabled = $appManager->isEnabledForUser('encryption'); @@ -394,10 +411,24 @@ class UsersController extends Controller { if($email !== '') { $user->setEMailAddress($email); + $token = $this->secureRandom->generate( + 21, + ISecureRandom::CHAR_DIGITS. + ISecureRandom::CHAR_LOWER. + ISecureRandom::CHAR_UPPER + ); + $tokenValue = $this->timeFactory->getTime() .':'. $token; + $mailAddress = !is_null($user->getEMailAddress()) ? $user->getEMailAddress() : ''; + $encryptedValue = $this->crypto->encrypt($tokenValue, $mailAddress.$this->config->getSystemValue('secret')); + $this->config->setUserValue($username, 'core', 'lostpassword', $encryptedValue); + + $link = $this->urlGenerator->linkToRouteAbsolute('core.lost.resetform', array('userId' => $username, 'token' => $token)); + + // data for the mail template $mailData = array( 'username' => $username, - 'url' => $this->urlGenerator->getAbsoluteURL('/') + 'url' =>$link ); $mail = new TemplateResponse('settings', 'email.new_user', $mailData, 'blank'); From a37f29964f86be5ec51fe33d32e290d3701828b2 Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Wed, 23 Nov 2016 21:30:15 +0100 Subject: [PATCH 2/7] add setting for "send password link" Signed-off-by: Morris Jobke --- lib/private/User/Manager.php | 6 ++--- settings/Controller/UsersController.php | 35 ++++++++++++++----------- settings/js/users/users.js | 24 ++++++++++++++++- settings/templates/users/main.php | 7 +++++ settings/users.php | 1 + 5 files changed, 53 insertions(+), 20 deletions(-) diff --git a/lib/private/User/Manager.php b/lib/private/User/Manager.php index 3d016700ee..cb726b55ea 100644 --- a/lib/private/User/Manager.php +++ b/lib/private/User/Manager.php @@ -282,9 +282,9 @@ class Manager extends PublicEmitter implements IUserManager { throw new \Exception($l->t('Username contains whitespace at the beginning or at the end')); } // No empty password - if (trim($password) == '') { - throw new \Exception($l->t('A valid password must be provided')); - } +// if (trim($password) == '') { +// throw new \Exception($l->t('A valid password must be provided')); +// } // Check if user already exists if ($this->userExists($uid)) { diff --git a/settings/Controller/UsersController.php b/settings/Controller/UsersController.php index f9be5468d3..b81b0f3ee9 100644 --- a/settings/Controller/UsersController.php +++ b/settings/Controller/UsersController.php @@ -51,7 +51,7 @@ use OCP\Mail\IMailer; use OCP\IAvatarManager; use OCP\Security\ICrypto; use OCP\Security\ISecureRandom; -use OC\AppFramework\Utility\TimeFactory; +use OCP\AppFramework\Utility\ITimeFactory; /** * @package OC\Settings\Controller @@ -89,7 +89,7 @@ class UsersController extends Controller { private $accountManager; /** @var ISecureRandom */ private $secureRandom; - /** @var TimeFactory */ + /** @var ITimeFactory */ private $timeFactory; /** @var ICrypto */ private $crypto; @@ -113,7 +113,7 @@ class UsersController extends Controller { * @param IAvatarManager $avatarManager * @param AccountManager $accountManager * @param ISecureRandom $secureRandom - * @param TimeFactory $timeFactory + * @param ITimeFactory $timeFactory * @param ICrypto $crypto */ public function __construct($appName, @@ -133,7 +133,7 @@ class UsersController extends Controller { IAvatarManager $avatarManager, AccountManager $accountManager, ISecureRandom $secureRandom, - TimeFactory $timeFactory, + ITimeFactory $timeFactory, ICrypto $crypto) { parent::__construct($appName, $request); $this->userManager = $userManager; @@ -411,19 +411,22 @@ class UsersController extends Controller { if($email !== '') { $user->setEMailAddress($email); - $token = $this->secureRandom->generate( - 21, - ISecureRandom::CHAR_DIGITS. - ISecureRandom::CHAR_LOWER. - ISecureRandom::CHAR_UPPER - ); - $tokenValue = $this->timeFactory->getTime() .':'. $token; - $mailAddress = !is_null($user->getEMailAddress()) ? $user->getEMailAddress() : ''; - $encryptedValue = $this->crypto->encrypt($tokenValue, $mailAddress.$this->config->getSystemValue('secret')); - $this->config->setUserValue($username, 'core', 'lostpassword', $encryptedValue); - - $link = $this->urlGenerator->linkToRouteAbsolute('core.lost.resetform', array('userId' => $username, 'token' => $token)); + if ($this->config->getAppValue('core', 'umgmt_send_passwordlink', 'false') === 'true') { + $token = $this->secureRandom->generate( + 21, + ISecureRandom::CHAR_DIGITS . + ISecureRandom::CHAR_LOWER . + ISecureRandom::CHAR_UPPER + ); + $tokenValue = $this->timeFactory->getTime() . ':' . $token; + $mailAddress = !is_null($user->getEMailAddress()) ? $user->getEMailAddress() : ''; + $encryptedValue = $this->crypto->encrypt($tokenValue, $mailAddress . $this->config->getSystemValue('secret')); + $this->config->setUserValue($username, 'core', 'lostpassword', $encryptedValue); + $link = $this->urlGenerator->linkToRouteAbsolute('core.lost.resetform', array('userId' => $username, 'token' => $token)); + } else { + $link = $this->urlGenerator->getAbsoluteURL('/'); + } // data for the mail template $mailData = array( diff --git a/settings/js/users/users.js b/settings/js/users/users.js index 3cf7b5e810..55939c289c 100644 --- a/settings/js/users/users.js +++ b/settings/js/users/users.js @@ -918,7 +918,7 @@ $(document).ready(function () { })); return false; } - if ($.trim(password) === '') { + if ($.trim(password) === '' && !$('#CheckboxMailPasswordOnUserCreate').is(':checked')) { OC.Notification.showTemporary(t('settings', 'Error creating user: {message}', { message: t('settings', 'A valid password must be provided') })); @@ -1044,15 +1044,37 @@ $(document).ready(function () { if ($('#CheckboxMailOnUserCreate').is(':checked')) { $("#newemail").show(); + $("#MailPasswordOnUserCreateSetting").show(); } + + if ($('#CheckboxMailPasswordOnUserCreate').is(':checked')) { + $("#newuserpassword").hide(); + } else { + $("#newuserpassword").show(); + } + // Option to display/hide the "E-Mail" input field $('#CheckboxMailOnUserCreate').click(function() { if ($('#CheckboxMailOnUserCreate').is(':checked')) { $("#newemail").show(); + $("#MailPasswordOnUserCreateSetting").show(); OCP.AppConfig.setValue('core', 'umgmt_send_email', 'true'); } else { $("#newemail").hide(); + $("#MailPasswordOnUserCreateSetting").hide(); OCP.AppConfig.setValue('core', 'umgmt_send_email', 'false'); + OCP.AppConfig.setValue('core', 'umgmt_send_passwordlink', 'false'); + $('#CheckboxMailPasswordOnUserCreate').removeAttr('checked'); + } + }); + + $('#CheckboxMailPasswordOnUserCreate').click(function() { + if ($('#CheckboxMailPasswordOnUserCreate').is(':checked')) { + OCP.AppConfig.setValue('core', 'umgmt_send_passwordlink', 'true'); + $("#newuserpassword").hide(); + } else { + OCP.AppConfig.setValue('core', 'umgmt_send_passwordlink', 'false'); + $("#newuserpassword").show(); } }); diff --git a/settings/templates/users/main.php b/settings/templates/users/main.php index b363a4c4da..59575a84e7 100644 --- a/settings/templates/users/main.php +++ b/settings/templates/users/main.php @@ -72,6 +72,13 @@ translation('settings'); t('Send email to new user')) ?>

+

+ /> + +

/> diff --git a/settings/users.php b/settings/users.php index 1b0f4f7b8e..2532acdbb1 100644 --- a/settings/users.php +++ b/settings/users.php @@ -124,5 +124,6 @@ $tmpl->assign('show_last_login', $config->getAppValue('core', 'umgmt_show_last_l $tmpl->assign('show_email', $config->getAppValue('core', 'umgmt_show_email', 'false')); $tmpl->assign('show_backend', $config->getAppValue('core', 'umgmt_show_backend', 'false')); $tmpl->assign('send_email', $config->getAppValue('core', 'umgmt_send_email', 'false')); +$tmpl->assign('send_passwordlink', $config->getAppValue('core', 'umgmt_send_passwordlink', 'false')); $tmpl->printPage(); From be139c85a8ea7809a710a4be57b40a9001026117 Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Wed, 23 Nov 2016 21:44:38 +0100 Subject: [PATCH 3/7] empty password only allowed if password link is sent Signed-off-by: Morris Jobke --- lib/private/User/Manager.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/private/User/Manager.php b/lib/private/User/Manager.php index cb726b55ea..39845fba88 100644 --- a/lib/private/User/Manager.php +++ b/lib/private/User/Manager.php @@ -281,10 +281,10 @@ class Manager extends PublicEmitter implements IUserManager { if (strlen(trim($uid, "\t\n\r\0\x0B\xe2\x80\x8b")) !== strlen(trim($uid))) { throw new \Exception($l->t('Username contains whitespace at the beginning or at the end')); } - // No empty password -// if (trim($password) == '') { -// throw new \Exception($l->t('A valid password must be provided')); -// } + // empty password only allowed if password link is sent + if (trim($password) == '' && $this->config->getAppValue('core', 'umgmt_send_passwordlink', 'false') === 'false') { + throw new \Exception($l->t('A valid password must be provided')); + } // Check if user already exists if ($this->userExists($uid)) { From c3fe8f6cf27f45d3fbcdc625ba547e3736edd07a Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Thu, 24 Nov 2016 19:30:36 +0100 Subject: [PATCH 4/7] use random password if "password link" is enabled Signed-off-by: Morris Jobke --- lib/private/User/Manager.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/private/User/Manager.php b/lib/private/User/Manager.php index 39845fba88..b1f328b6f1 100644 --- a/lib/private/User/Manager.php +++ b/lib/private/User/Manager.php @@ -281,9 +281,11 @@ class Manager extends PublicEmitter implements IUserManager { if (strlen(trim($uid, "\t\n\r\0\x0B\xe2\x80\x8b")) !== strlen(trim($uid))) { throw new \Exception($l->t('Username contains whitespace at the beginning or at the end')); } - // empty password only allowed if password link is sent + // if password link is sent use random password; permit empty password if (trim($password) == '' && $this->config->getAppValue('core', 'umgmt_send_passwordlink', 'false') === 'false') { throw new \Exception($l->t('A valid password must be provided')); + } else { + $password = \OC::$server->getSecureRandom()->generate(32); } // Check if user already exists From 2e88bec14bb9cee82c1f3e5479c081eeadd89be5 Mon Sep 17 00:00:00 2001 From: Morris Jobke Date: Wed, 15 Feb 2017 12:17:55 -0600 Subject: [PATCH 5/7] Fix setup issue and refine error messages Signed-off-by: Morris Jobke --- core/css/apps.scss | 5 +++++ lib/private/User/Manager.php | 6 ++---- settings/Controller/UsersController.php | 19 +++++++++++++++++-- settings/js/users/users.js | 24 +----------------------- settings/templates/users/main.php | 8 ++------ settings/users.php | 1 - 6 files changed, 27 insertions(+), 36 deletions(-) diff --git a/core/css/apps.scss b/core/css/apps.scss index f1ddc95e09..91805fe16b 100644 --- a/core/css/apps.scss +++ b/core/css/apps.scss @@ -420,6 +420,11 @@ em { input[type='text'] { width: 93%; } + + .info-text { + padding: 5px 0 7px 22px; + color: #999; + } } #app-settings-header { diff --git a/lib/private/User/Manager.php b/lib/private/User/Manager.php index b1f328b6f1..3d016700ee 100644 --- a/lib/private/User/Manager.php +++ b/lib/private/User/Manager.php @@ -281,11 +281,9 @@ class Manager extends PublicEmitter implements IUserManager { if (strlen(trim($uid, "\t\n\r\0\x0B\xe2\x80\x8b")) !== strlen(trim($uid))) { throw new \Exception($l->t('Username contains whitespace at the beginning or at the end')); } - // if password link is sent use random password; permit empty password - if (trim($password) == '' && $this->config->getAppValue('core', 'umgmt_send_passwordlink', 'false') === 'false') { + // No empty password + if (trim($password) == '') { throw new \Exception($l->t('A valid password must be provided')); - } else { - $password = \OC::$server->getSecureRandom()->generate(32); } // Check if user already exists diff --git a/settings/Controller/UsersController.php b/settings/Controller/UsersController.php index b81b0f3ee9..fb5e6af04a 100644 --- a/settings/Controller/UsersController.php +++ b/settings/Controller/UsersController.php @@ -379,6 +379,21 @@ class UsersController extends Controller { ); } + $generatedPassword = false; + if ($password === '') { + if ($email === '') { + return new DataResponse( + array( + 'message' => (string)$this->l10n->t('To send a password link to the user an email address is required.') + ), + Http::STATUS_UNPROCESSABLE_ENTITY + ); + } + + $password = $this->secureRandom->generate(32); + $generatedPassword = true; + } + try { $user = $this->userManager->createUser($username, $password); } catch (\Exception $exception) { @@ -411,7 +426,7 @@ class UsersController extends Controller { if($email !== '') { $user->setEMailAddress($email); - if ($this->config->getAppValue('core', 'umgmt_send_passwordlink', 'false') === 'true') { + if ($generatedPassword) { $token = $this->secureRandom->generate( 21, ISecureRandom::CHAR_DIGITS . @@ -431,7 +446,7 @@ class UsersController extends Controller { // data for the mail template $mailData = array( 'username' => $username, - 'url' =>$link + 'url' => $link ); $mail = new TemplateResponse('settings', 'email.new_user', $mailData, 'blank'); diff --git a/settings/js/users/users.js b/settings/js/users/users.js index 55939c289c..a6dcafcdac 100644 --- a/settings/js/users/users.js +++ b/settings/js/users/users.js @@ -918,7 +918,7 @@ $(document).ready(function () { })); return false; } - if ($.trim(password) === '' && !$('#CheckboxMailPasswordOnUserCreate').is(':checked')) { + if ($.trim(password) === '' && !$('#CheckboxMailOnUserCreate').is(':checked')) { OC.Notification.showTemporary(t('settings', 'Error creating user: {message}', { message: t('settings', 'A valid password must be provided') })); @@ -1044,37 +1044,15 @@ $(document).ready(function () { if ($('#CheckboxMailOnUserCreate').is(':checked')) { $("#newemail").show(); - $("#MailPasswordOnUserCreateSetting").show(); } - - if ($('#CheckboxMailPasswordOnUserCreate').is(':checked')) { - $("#newuserpassword").hide(); - } else { - $("#newuserpassword").show(); - } - // Option to display/hide the "E-Mail" input field $('#CheckboxMailOnUserCreate').click(function() { if ($('#CheckboxMailOnUserCreate').is(':checked')) { $("#newemail").show(); - $("#MailPasswordOnUserCreateSetting").show(); OCP.AppConfig.setValue('core', 'umgmt_send_email', 'true'); } else { $("#newemail").hide(); - $("#MailPasswordOnUserCreateSetting").hide(); OCP.AppConfig.setValue('core', 'umgmt_send_email', 'false'); - OCP.AppConfig.setValue('core', 'umgmt_send_passwordlink', 'false'); - $('#CheckboxMailPasswordOnUserCreate').removeAttr('checked'); - } - }); - - $('#CheckboxMailPasswordOnUserCreate').click(function() { - if ($('#CheckboxMailPasswordOnUserCreate').is(':checked')) { - OCP.AppConfig.setValue('core', 'umgmt_send_passwordlink', 'true'); - $("#newuserpassword").hide(); - } else { - OCP.AppConfig.setValue('core', 'umgmt_send_passwordlink', 'false'); - $("#newuserpassword").show(); } }); diff --git a/settings/templates/users/main.php b/settings/templates/users/main.php index 59575a84e7..44121a38d9 100644 --- a/settings/templates/users/main.php +++ b/settings/templates/users/main.php @@ -72,12 +72,8 @@ translation('settings'); t('Send email to new user')) ?>

-

- /> - +

+ When the password of the new user is left empty an activation email with a link to set the password is send to the user.

assign('show_last_login', $config->getAppValue('core', 'umgmt_show_last_l $tmpl->assign('show_email', $config->getAppValue('core', 'umgmt_show_email', 'false')); $tmpl->assign('show_backend', $config->getAppValue('core', 'umgmt_show_backend', 'false')); $tmpl->assign('send_email', $config->getAppValue('core', 'umgmt_send_email', 'false')); -$tmpl->assign('send_passwordlink', $config->getAppValue('core', 'umgmt_send_passwordlink', 'false')); $tmpl->printPage(); From abb496a43902c28fc253548d93407639deb338d3 Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma Date: Wed, 15 Feb 2017 20:30:55 +0100 Subject: [PATCH 6/7] Add l10n Signed-off-by: Roeland Jago Douma --- settings/templates/users/main.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings/templates/users/main.php b/settings/templates/users/main.php index 44121a38d9..59ddf6a1dd 100644 --- a/settings/templates/users/main.php +++ b/settings/templates/users/main.php @@ -73,7 +73,7 @@ translation('settings');

- When the password of the new user is left empty an activation email with a link to set the password is send to the user. + t('When the password of the new user is left empty an activation email with a link to set the password is send to the user')) ?>

Date: Wed, 15 Feb 2017 18:07:21 -0600 Subject: [PATCH 7/7] add unit tests Signed-off-by: Morris Jobke --- settings/Controller/UsersController.php | 2 +- .../Controller/UsersControllerTest.php | 168 +++++++++++++++++- 2 files changed, 166 insertions(+), 4 deletions(-) diff --git a/settings/Controller/UsersController.php b/settings/Controller/UsersController.php index fb5e6af04a..19c5b06816 100644 --- a/settings/Controller/UsersController.php +++ b/settings/Controller/UsersController.php @@ -438,7 +438,7 @@ class UsersController extends Controller { $encryptedValue = $this->crypto->encrypt($tokenValue, $mailAddress . $this->config->getSystemValue('secret')); $this->config->setUserValue($username, 'core', 'lostpassword', $encryptedValue); - $link = $this->urlGenerator->linkToRouteAbsolute('core.lost.resetform', array('userId' => $username, 'token' => $token)); + $link = $this->urlGenerator->linkToRouteAbsolute('core.lost.resetform', ['userId' => $username, 'token' => $token]); } else { $link = $this->urlGenerator->getAbsoluteURL('/'); } diff --git a/tests/Settings/Controller/UsersControllerTest.php b/tests/Settings/Controller/UsersControllerTest.php index 4f10fed1a2..3cdde1b2d2 100644 --- a/tests/Settings/Controller/UsersControllerTest.php +++ b/tests/Settings/Controller/UsersControllerTest.php @@ -16,6 +16,7 @@ use OC\Settings\Controller\UsersController; use OCP\App\IAppManager; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\Utility\ITimeFactory; use OCP\IAvatar; use OCP\IAvatarManager; use OCP\IConfig; @@ -29,6 +30,8 @@ use OCP\IUser; use OCP\IUserManager; use OCP\IUserSession; use OCP\Mail\IMailer; +use OCP\Security\ICrypto; +use OCP\Security\ISecureRandom; /** * @group DB @@ -59,8 +62,14 @@ class UsersControllerTest extends \Test\TestCase { private $avatarManager; /** @var IL10N|\PHPUnit_Framework_MockObject_MockObject */ private $l; - /** @var AccountManager | \PHPUnit_Framework_MockObject_MockObject */ + /** @var AccountManager | \PHPUnit_Framework_MockObject_MockObject */ private $accountManager; + /** @var ISecureRandom | \PHPUnit_Framework_MockObject_MockObject */ + private $secureRandom; + /** @var ITimeFactory | \PHPUnit_Framework_MockObject_MockObject */ + private $timeFactory; + /** @var ICrypto | \PHPUnit_Framework_MockObject_MockObject */ + private $crypto; protected function setUp() { parent::setUp(); @@ -76,6 +85,9 @@ class UsersControllerTest extends \Test\TestCase { $this->appManager = $this->createMock(IAppManager::class); $this->avatarManager = $this->createMock(IAvatarManager::class); $this->accountManager = $this->createMock(AccountManager::class); + $this->secureRandom = $this->createMock(ISecureRandom::class); + $this->timeFactory = $this->createMock(ITimeFactory::class); + $this->crypto = $this->createMock(ICrypto::class); $this->l = $this->createMock(IL10N::class); $this->l->method('t') ->will($this->returnCallback(function ($text, $parameters = []) { @@ -120,7 +132,10 @@ class UsersControllerTest extends \Test\TestCase { $this->urlGenerator, $this->appManager, $this->avatarManager, - $this->accountManager + $this->accountManager, + $this->secureRandom, + $this->timeFactory, + $this->crypto ); } else { return $this->getMockBuilder(UsersController::class) @@ -141,7 +156,10 @@ class UsersControllerTest extends \Test\TestCase { $this->urlGenerator, $this->appManager, $this->avatarManager, - $this->accountManager + $this->accountManager, + $this->secureRandom, + $this->timeFactory, + $this->crypto ] )->setMethods($mockedMethods)->getMock(); } @@ -2227,4 +2245,148 @@ class UsersControllerTest extends \Test\TestCase { $response = $controller->setEMailAddress($user->getUID(), $mailAddress); $this->assertSame($responseCode, $response->getStatus()); } + + public function testCreateUnsuccessfulWithoutPasswordAndEmail() { + $controller = $this->getController(true); + + $expectedResponse = new DataResponse( + array( + 'message' => 'To send a password link to the user an email address is required.' + ), + Http::STATUS_UNPROCESSABLE_ENTITY + ); + $response = $controller->create('foo', '', array(), ''); + $this->assertEquals($expectedResponse, $response); + } + + + + public function testCreateSuccessfulWithoutPasswordAndWithEmail() { + $controller = $this->getController(true); + + $user = $this->getMockBuilder('\OC\User\User') + ->disableOriginalConstructor()->getMock(); + $user + ->method('getHome') + ->will($this->returnValue('/home/user')); + $user + ->method('getUID') + ->will($this->returnValue('foo')); + $user + ->expects($this->once()) + ->method('getBackendClassName') + ->will($this->returnValue('bar')); + + $this->userManager + ->expects($this->once()) + ->method('createUser') + ->will($this->onConsecutiveCalls($user)); + + $subadmin = $this->getMockBuilder('\OC\SubAdmin') + ->disableOriginalConstructor() + ->getMock(); + $subadmin + ->expects($this->any()) + ->method('getSubAdminsGroups') + ->with($user) + ->will($this->returnValue([])); + $this->groupManager + ->expects($this->any()) + ->method('getSubAdmin') + ->will($this->returnValue($subadmin)); + + $this->secureRandom + ->expects($this->at(0)) + ->method('generate') + ->with(32) + ->will($this->returnValue('abc123')); + $this->secureRandom + ->expects($this->at(1)) + ->method('generate') + ->with(21, + ISecureRandom::CHAR_DIGITS . + ISecureRandom::CHAR_LOWER . + ISecureRandom::CHAR_UPPER) + ->will($this->returnValue('mytoken')); + $this->urlGenerator + ->expects($this->once()) + ->method('linkToRouteAbsolute') + ->with('core.lost.resetform', ['userId' => 'foo', 'token' => 'mytoken']) + ->will($this->returnValue('link-with-my-token')); + + $controller = $this->getController(true); + $message = $this->getMockBuilder('\OC\Mail\Message') + ->disableOriginalConstructor()->getMock(); + $message + ->expects($this->at(0)) + ->method('setTo') + ->with(['abc@example.org' => 'foo']); + $message + ->expects($this->at(1)) + ->method('setSubject') + ->with('Your account was created'); + $htmlBody = new Http\TemplateResponse( + 'settings', + 'email.new_user', + [ + 'username' => 'foo', + 'url' => 'link-with-my-token', + ], + 'blank' + ); + $message + ->expects($this->at(2)) + ->method('setHtmlBody') + ->with($htmlBody->render()); + $plainBody = new Http\TemplateResponse( + 'settings', + 'email.new_user_plain_text', + [ + 'username' => 'foo', + 'url' => 'link-with-my-token', + ], + 'blank' + ); + $message + ->expects($this->at(3)) + ->method('setPlainBody') + ->with($plainBody->render()); + $message + ->expects($this->at(4)) + ->method('setFrom') + ->with(['no-reply@owncloud.com' => null]); + + $this->mailer + ->expects($this->at(0)) + ->method('validateMailAddress') + ->with('abc@example.org') + ->will($this->returnValue(true)); + $this->mailer + ->expects($this->at(1)) + ->method('createMessage') + ->will($this->returnValue($message)); + $this->mailer + ->expects($this->at(2)) + ->method('send') + ->with($message); + + $expectedResponse = new DataResponse( + array( + 'name' => 'foo', + 'groups' => null, + 'storageLocation' => '/home/user', + 'backend' => 'bar', + 'lastLogin' => null, + 'displayname' => null, + 'quota' => null, + 'subadmin' => array(), + 'email' => null, + 'isRestoreDisabled' => false, + 'isAvatarAvailable' => true, + ), + Http::STATUS_CREATED + ); + $response = $controller->create('foo', '', array(), 'abc@example.org'); + $this->assertEquals($expectedResponse, $response); + } }