summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorblizzz <blizzz@arthur-schiwon.de>2019-06-21 11:08:59 +0200
committerGitHub <noreply@github.com>2019-06-21 11:08:59 +0200
commitc1eff72bdf91df623bb377967270befd5c1594f9 (patch)
treeec79e8297f225212bebbf3ef64b1e2e6106f937f /apps
parent08734326da2bf8aef1856129ac547e6d4358d805 (diff)
parent29449f85b688deb1f103f3f67993475a040b4d80 (diff)
downloadnextcloud-server-c1eff72bdf91df623bb377967270befd5c1594f9.tar.gz
nextcloud-server-c1eff72bdf91df623bb377967270befd5c1594f9.zip
Merge pull request #15964 from nextcloud/enh/noid/user-creation-options
Opt-in for generation userid, requiring email addresses
Diffstat (limited to 'apps')
-rw-r--r--apps/provisioning_api/lib/Controller/UsersController.php26
-rw-r--r--apps/provisioning_api/tests/Controller/UsersControllerTest.php159
-rw-r--r--apps/user_ldap/lib/Access.php2
-rw-r--r--apps/user_ldap/lib/Group_LDAP.php2
-rw-r--r--apps/user_ldap/lib/User_LDAP.php22
-rw-r--r--apps/user_ldap/tests/User_LDAPTest.php19
6 files changed, 218 insertions, 12 deletions
diff --git a/apps/provisioning_api/lib/Controller/UsersController.php b/apps/provisioning_api/lib/Controller/UsersController.php
index b993188c97e..252db66c35e 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;
@@ -197,6 +196,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) && $this->config->getAppValue('core', 'newUser.generateUserID', 'no') === 'yes') {
+ $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 === '' && $this->config->getAppValue('core', 'newUser.requireEmail', 'no') === 'yes') {
+ 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 7a7f0144524..63f9d4c376a 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 'yes';
+ }
+ 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 'yes';
+ }
+ 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 'yes';
+ }
+ 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()
+ ));
}
/**
diff --git a/apps/user_ldap/lib/Access.php b/apps/user_ldap/lib/Access.php
index 6a074bbed2e..5db9dddf8fa 100644
--- a/apps/user_ldap/lib/Access.php
+++ b/apps/user_ldap/lib/Access.php
@@ -635,7 +635,7 @@ class Access extends LDAPUtility {
return false;
}
- protected function mapAndAnnounceIfApplicable(
+ public function mapAndAnnounceIfApplicable(
AbstractMapping $mapper,
string $fdn,
string $name,
diff --git a/apps/user_ldap/lib/Group_LDAP.php b/apps/user_ldap/lib/Group_LDAP.php
index 5b25979b2d2..d9059b2372f 100644
--- a/apps/user_ldap/lib/Group_LDAP.php
+++ b/apps/user_ldap/lib/Group_LDAP.php
@@ -110,7 +110,7 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLD
$members = $this->access->connection->getFromCache($cacheKeyMembers);
if(!is_null($members)) {
$this->cachedGroupMembers[$gid] = $members;
- $isInGroup = in_array($userDN, $members);
+ $isInGroup = in_array($userDN, $members, true);
$this->access->connection->writeToCache($cacheKey, $isInGroup);
return $isInGroup;
}
diff --git a/apps/user_ldap/lib/User_LDAP.php b/apps/user_ldap/lib/User_LDAP.php
index ada07aa53a9..5e06547533d 100644
--- a/apps/user_ldap/lib/User_LDAP.php
+++ b/apps/user_ldap/lib/User_LDAP.php
@@ -622,8 +622,26 @@ class User_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
if ($this->userPluginManager->implementsActions(Backend::CREATE_USER)) {
if ($dn = $this->userPluginManager->createUser($username, $password)) {
if (is_string($dn)) {
- //updates user mapping
- $this->access->dn2ocname($dn, $username, true);
+ // the NC user creation work flow requires a know user id up front
+ $uuid = $this->access->getUUID($dn, true);
+ if(is_string($uuid)) {
+ $this->access->mapAndAnnounceIfApplicable(
+ $this->access->getUserMapper(),
+ $dn,
+ $username,
+ $uuid,
+ true
+ );
+ $this->access->cacheUserExists($username);
+ } else {
+ \OC::$server->getLogger()->warning(
+ 'Failed to map created LDAP user with userid {userid}, because UUID could not be determined',
+ [
+ 'app' => 'user_ldap',
+ 'userid' => $username,
+ ]
+ );
+ }
} else {
throw new \UnexpectedValueException("LDAP Plugin: Method createUser changed to return the user DN instead of boolean.");
}
diff --git a/apps/user_ldap/tests/User_LDAPTest.php b/apps/user_ldap/tests/User_LDAPTest.php
index e4f7bb8b6d2..9b8bda2b808 100644
--- a/apps/user_ldap/tests/User_LDAPTest.php
+++ b/apps/user_ldap/tests/User_LDAPTest.php
@@ -35,6 +35,7 @@ use OC\User\Backend;
use OC\User\Session;
use OCA\User_LDAP\Access;
use OCA\User_LDAP\Connection;
+use OCA\User_LDAP\Mapping\AbstractMapping;
use OCA\User_LDAP\Mapping\UserMapping;
use OCA\User_LDAP\User\Manager;
use OCA\User_LDAP\User\OfflineUser;
@@ -1437,16 +1438,30 @@ class User_LDAPTest extends TestCase {
}
public function testCreateUserWithPlugin() {
+ $uid = 'alien6372';
+ $uuid = '123-2345-36756-123-2345234-4431';
+ $pwd = 'passwørd';
+
$this->pluginManager->expects($this->once())
->method('implementsActions')
->with(Backend::CREATE_USER)
->willReturn(true);
$this->pluginManager->expects($this->once())
->method('createUser')
- ->with('uid','password')
+ ->with($uid, $pwd)
->willReturn('result');
- $this->assertEquals($this->backend->createUser('uid', 'password'),true);
+ $this->access->expects($this->atLeastOnce())
+ ->method('getUUID')
+ ->willReturn($uuid);
+ $this->access->expects($this->once())
+ ->method('mapAndAnnounceIfApplicable')
+ ->with($this->isInstanceOf(AbstractMapping::class), $this->anything(), $uid, $uuid, true);
+ $this->access->expects($this->any())
+ ->method('getUserMapper')
+ ->willReturn($this->createMock(AbstractMapping::class));
+
+ $this->assertEquals($this->backend->createUser($uid, $pwd),true);
}
public function testCreateUserFailing() {