From 5b754a6353d31f0548860f1b17b7c9db0f2ee791 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Fri, 14 Jun 2019 17:07:40 +0200 Subject: [PATCH] extends Provisioning API with optional userid and required email Signed-off-by: Arthur Schiwon --- .../lib/Controller/UsersController.php | 26 ++- .../tests/Controller/UsersControllerTest.php | 159 +++++++++++++++++- 2 files changed, 179 insertions(+), 6 deletions(-) diff --git a/apps/provisioning_api/lib/Controller/UsersController.php b/apps/provisioning_api/lib/Controller/UsersController.php index b993188c97..dfc9d188b5 100644 --- a/apps/provisioning_api/lib/Controller/UsersController.php +++ b/apps/provisioning_api/lib/Controller/UsersController.php @@ -46,7 +46,6 @@ use OCP\IGroup; use OCP\IGroupManager; use OCP\ILogger; use OCP\IRequest; -use OCP\IUser; use OCP\IUserManager; use OCP\IUserSession; use OCP\L10N\IFactory; @@ -196,6 +195,21 @@ class UsersController extends AUserData { ]); } + /** + * @throws OCSException + */ + private function createNewUserId(): string { + $attempts = 0; + do { + $uidCandidate = $this->secureRandom->generate(10, ISecureRandom::CHAR_HUMAN_READABLE); + if (!$this->userManager->userExists($uidCandidate)) { + return $uidCandidate; + } + $attempts++; + } while ($attempts < 10); + throw new OCSException('Could not create non-existing user id', 111); + } + /** * @PasswordConfirmationRequired * @NoAdminRequired @@ -223,6 +237,10 @@ class UsersController extends AUserData { $isAdmin = $this->groupManager->isAdmin($user->getUID()); $subAdminManager = $this->groupManager->getSubAdmin(); + if(empty($userid) && (bool)$this->config->getAppValue('settings', 'newUser.generateUserID', false)) { + $userid = $this->createNewUserId(); + } + if ($this->userManager->userExists($userid)) { $this->logger->error('Failed addUser attempt: User already exists.', ['app' => 'ocs_api']); throw new OCSException('User already exists', 102); @@ -275,6 +293,10 @@ class UsersController extends AUserData { $generatePasswordResetToken = true; } + if ($email === '' && (bool)$this->config->getAppValue('settings', 'newUser.requireEmail', false)) { + throw new OCSException('Required email address was not provided', 110); + } + try { $newUser = $this->userManager->createUser($userid, $password); $this->logger->info('Successful addUser call with userid: ' . $userid, ['app' => 'ocs_api']); @@ -315,7 +337,7 @@ class UsersController extends AUserData { } } - return new DataResponse(); + return new DataResponse(['UserID' => $userid]); } catch (HintException $e ) { $this->logger->logException($e, [ diff --git a/apps/provisioning_api/tests/Controller/UsersControllerTest.php b/apps/provisioning_api/tests/Controller/UsersControllerTest.php index 7a7f014452..b064f019f0 100644 --- a/apps/provisioning_api/tests/Controller/UsersControllerTest.php +++ b/apps/provisioning_api/tests/Controller/UsersControllerTest.php @@ -356,7 +356,10 @@ class UsersControllerTest extends TestCase { ->with('adminUser') ->willReturn(true); - $this->assertEquals([], $this->api->addUser('NewUser', 'PasswordOfTheNewUser')->getData()); + $this->assertTrue(key_exists( + 'UserID', + $this->api->addUser('NewUser', 'PasswordOfTheNewUser')->getData() + )); } public function testAddUserSuccessfulWithDisplayName() { @@ -413,7 +416,149 @@ class UsersControllerTest extends TestCase { ->method('editUser') ->with('NewUser', 'display', 'DisplayNameOfTheNewUser'); - $this->assertEquals([], $api->addUser('NewUser', 'PasswordOfTheNewUser', 'DisplayNameOfTheNewUser')->getData()); + $this->assertTrue(key_exists( + 'UserID', + $api->addUser('NewUser', 'PasswordOfTheNewUser', 'DisplayNameOfTheNewUser')->getData() + )); + } + + public function testAddUserSuccessfulGenerateUserID() { + $this->config + ->expects($this->any()) + ->method('getAppValue') + ->willReturnCallback(function($appid, $key, $default) { + if($key === 'newUser.generateUserID') { + return true; + } + return null; + }); + $this->userManager + ->expects($this->any()) + ->method('userExists') + ->with($this->anything()) + ->will($this->returnValue(false)); + $this->userManager + ->expects($this->once()) + ->method('createUser') + ->with($this->anything(), 'PasswordOfTheNewUser'); + $this->logger + ->expects($this->once()) + ->method('info') + ->with($this->stringStartsWith('Successful addUser call with userid: '), ['app' => 'ocs_api']); + $loggedInUser = $this->getMockBuilder(IUser::class) + ->disableOriginalConstructor() + ->getMock(); + $loggedInUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('adminUser')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('adminUser') + ->willReturn(true); + $this->secureRandom->expects($this->any()) + ->method('generate') + ->with(10) + ->willReturnCallback(function() { return (string)rand(1000000000, 9999999999); }); + + $this->assertTrue(key_exists( + 'UserID', + $this->api->addUser('', 'PasswordOfTheNewUser')->getData() + )); + } + + /** + * @expectedException \OCP\AppFramework\OCS\OCSException + * @expectedExceptionCode 111 + * @expectedExceptionMessage Could not create non-existing user id + */ + public function testAddUserFailedToGenerateUserID() { + $this->config + ->expects($this->any()) + ->method('getAppValue') + ->willReturnCallback(function($appid, $key, $default) { + if($key === 'newUser.generateUserID') { + return true; + } + return null; + }); + $this->userManager + ->expects($this->any()) + ->method('userExists') + ->with($this->anything()) + ->will($this->returnValue(true)); + $this->userManager + ->expects($this->never()) + ->method('createUser'); + $loggedInUser = $this->getMockBuilder(IUser::class) + ->disableOriginalConstructor() + ->getMock(); + $loggedInUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('adminUser')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('adminUser') + ->willReturn(true); + + $this->api->addUser('', 'PasswordOfTheNewUser')->getData(); + } + + /** + * @expectedException \OCP\AppFramework\OCS\OCSException + * @expectedExceptionCode 110 + * @expectedExceptionMessage Required email address was not provided + */ + public function testAddUserEmailRequired() { + $this->config + ->expects($this->any()) + ->method('getAppValue') + ->willReturnCallback(function($appid, $key, $default) { + if($key === 'newUser.requireEmail') { + return true; + } + return null; + }); + $this->userManager + ->expects($this->once()) + ->method('userExists') + ->with('NewUser') + ->will($this->returnValue(false)); + $this->userManager + ->expects($this->never()) + ->method('createUser'); + $loggedInUser = $this->getMockBuilder(IUser::class) + ->disableOriginalConstructor() + ->getMock(); + $loggedInUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('adminUser')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('adminUser') + ->willReturn(true); + + $this->assertTrue(key_exists( + 'UserID', + $this->api->addUser('NewUser', 'PasswordOfTheNewUser')->getData() + )); } public function testAddUserExistingGroup() { @@ -471,7 +616,10 @@ class UsersControllerTest extends TestCase { ['Added userid NewUser to group ExistingGroup', ['app' => 'ocs_api']] ); - $this->assertEquals([], $this->api->addUser('NewUser', 'PasswordOfTheNewUser', '', '', ['ExistingGroup'])->getData()); + $this->assertTrue(key_exists( + 'UserID', + $this->api->addUser('NewUser', 'PasswordOfTheNewUser', '', '', ['ExistingGroup'])->getData() + )); } /** @@ -689,7 +837,10 @@ class UsersControllerTest extends TestCase { ) ->willReturn(true); - $this->assertEquals([], $this->api->addUser('NewUser', 'PasswordOfTheNewUser', '', '', ['ExistingGroup1', 'ExistingGroup2'])->getData()); + $this->assertTrue(key_exists( + 'UserID', + $this->api->addUser('NewUser', 'PasswordOfTheNewUser', '', '', ['ExistingGroup1', 'ExistingGroup2'])->getData() + )); } /**