Merge pull request #22102 from owncloud/ldap_2nddispname-master

[LDAP] add second field for additional/optional display name attribute
This commit is contained in:
Thomas Müller 2016-02-06 13:27:01 +01:00
commit 69a4cd2898
11 changed files with 209 additions and 15 deletions

View file

@ -55,6 +55,10 @@ OCA = OCA || {};
$element: $('#ldap_display_name'),
setMethod: 'setUserDisplayName'
},
ldap_user_display_name_2: {
$element: $('#ldap_user_display_name_2'),
setMethod: 'setUserDisplayName2'
},
ldap_base_users: {
$element: $('#ldap_base_users'),
setMethod: 'setBaseDNUsers'
@ -194,6 +198,15 @@ OCA = OCA || {};
this.setElementValue(this.managedItems.ldap_display_name.$element, attribute);
},
/**
* sets the additional user display name attribute
*
* @param {string} attribute
*/
setUserDisplayName2: function(attribute) {
this.setElementValue(this.managedItems.ldap_user_display_name_2.$element, attribute);
},
/**
* sets the Base DN for users
*

View file

@ -521,6 +521,7 @@ class Access extends LDAPUtility implements user\IUserTools {
private function ldap2ownCloudNames($ldapObjects, $isUsers) {
if($isUsers) {
$nameAttribute = $this->connection->ldapUserDisplayName;
$sndAttribute = $this->connection->ldapUserDisplayName2;
} else {
$nameAttribute = $this->connection->ldapGroupDisplayName;
}
@ -542,13 +543,14 @@ class Access extends LDAPUtility implements user\IUserTools {
if($isUsers) {
//cache the user names so it does not need to be retrieved
//again later (e.g. sharing dialogue).
$this->cacheUserExists($ocName);
if(!is_null($nameByLDAP)) {
$this->cacheUserDisplayName($ocName, $nameByLDAP);
if(is_null($nameByLDAP)) {
continue;
}
$sndName = isset($ldapObject[$sndAttribute])
? $ldapObject[$sndAttribute] : '';
$this->cacheUserDisplayName($ocName, $nameByLDAP, $sndName);
}
}
continue;
}
return $ownCloudNames;
}
@ -575,8 +577,11 @@ class Access extends LDAPUtility implements user\IUserTools {
* caches the user display name
* @param string $ocName the internal ownCloud username
* @param string $displayName the display name
* @param string $displayName2 the second display name
*/
public function cacheUserDisplayName($ocName, $displayName) {
public function cacheUserDisplayName($ocName, $displayName, $displayName2 = '') {
$user = $this->userManager->get($ocName);
$displayName = $user->composeAndStoreDisplayName($displayName, $displayName2);
$cacheKeyTrunk = 'getDisplayName';
$this->connection->writeToCache($cacheKeyTrunk.$ocName, $displayName);
}
@ -1300,7 +1305,7 @@ class Access extends LDAPUtility implements user\IUserTools {
return false;
}
$result=$testConnection->bind();
$this->connection->bind();
$this->ldap->unbind($this->connection->getConnectionResource());
return $result;
}

View file

@ -48,6 +48,7 @@ class Configuration {
'turnOffCertCheck' => null,
'ldapIgnoreNamingRules' => null,
'ldapUserDisplayName' => null,
'ldapUserDisplayName2' => null,
'ldapUserFilterObjectclass' => null,
'ldapUserFilterGroups' => null,
'ldapUserFilter' => null,
@ -208,6 +209,7 @@ class Configuration {
case 'ldapAgentPassword':
$readMethod = 'getPwd';
break;
case 'ldapUserDisplayName2':
case 'ldapGroupDisplayName':
$readMethod = 'getLcValue';
break;
@ -418,6 +420,7 @@ class Configuration {
'ldap_groupfilter_objectclass' => '',
'ldap_groupfilter_groups' => '',
'ldap_display_name' => 'displayName',
'ldap_user_display_name_2' => '',
'ldap_group_display_name' => 'cn',
'ldap_tls' => 0,
'ldap_quota_def' => '',
@ -475,6 +478,7 @@ class Configuration {
'ldap_groupfilter_objectclass' => 'ldapGroupFilterObjectclass',
'ldap_groupfilter_groups' => 'ldapGroupFilterGroups',
'ldap_display_name' => 'ldapUserDisplayName',
'ldap_user_display_name_2' => 'ldapUserDisplayName2',
'ldap_group_display_name' => 'ldapGroupDisplayName',
'ldap_tls' => 'ldapTLS',
'ldap_quota_def' => 'ldapQuotaDefault',

View file

@ -37,6 +37,7 @@ use OC\ServerNotAvailableException;
*
* @property string ldapUserFilter
* @property string ldapUserDisplayName
* @property string ldapUserDisplayName2
* @property boolean hasPagedResultSupport
* @property string[] ldapBaseUsers
* @property int|string ldapPagingSize holds an integer

View file

@ -147,6 +147,7 @@ class Manager {
$this->access->getConnection()->ldapQuotaAttribute,
$this->access->getConnection()->ldapEmailAttribute,
$this->access->getConnection()->ldapUserDisplayName,
$this->access->getConnection()->ldapUserDisplayName2,
);
foreach($possible as $attr) {
if(!is_null($attr)) {

View file

@ -168,13 +168,22 @@ class User {
unset($attr);
//displayName
$displayName = $displayName2 = '';
$attr = strtolower($this->connection->ldapUserDisplayName);
if(isset($ldapEntry[$attr])) {
$displayName = $ldapEntry[$attr][0];
if(!empty($displayName)) {
$this->storeDisplayName($displayName);
$this->access->cacheUserDisplayName($this->getUsername(), $displayName);
}
}
$attr = strtolower($this->connection->ldapUserDisplayName2);
if(isset($ldapEntry[$attr])) {
$displayName2 = $ldapEntry[$attr][0];
}
if(!empty($displayName)) {
$this->composeAndStoreDisplayName($displayName);
$this->access->cacheUserDisplayName(
$this->getUsername(),
$displayName,
$displayName2
);
}
unset($attr);
@ -350,6 +359,7 @@ class User {
/**
* Stores a key-value pair in relation to this user
*
* @param string $key
* @param string $value
*/
@ -358,11 +368,19 @@ class User {
}
/**
* Stores the display name in the databae
* Composes the display name and stores it in the database. The final
* display name is returned.
*
* @param string $displayName
* @param string $displayName2
* @returns string the effective display name
*/
public function storeDisplayName($displayName) {
public function composeAndStoreDisplayName($displayName, $displayName2 = '') {
if(!empty($displayName2)) {
$displayName .= ' (' . $displayName2 . ')';
}
$this->store('displayName', $displayName);
return $displayName;
}
/**

View file

@ -84,6 +84,7 @@ style('user_ldap', 'settings');
<h3><?php p($l->t('Directory Settings'));?></h3>
<div>
<p><label for="ldap_display_name"><?php p($l->t('User Display Name Field'));?></label><input type="text" id="ldap_display_name" name="ldap_display_name" data-default="<?php p($_['ldap_display_name_default']); ?>" title="<?php p($l->t('The LDAP attribute to use to generate the user\'s display name.'));?>" /></p>
<p><label for="ldap_user_display_name_2"><?php p($l->t('2nd User Display Name Field'));?></label><input type="text" id="ldap_user_display_name_2" name="ldap_user_display_name_2" data-default="<?php p($_['ldap_user_display_name_2_default']); ?>" title="<?php p($l->t('Optional. An LDAP attribute to be added to the display name in brackets. Results in e.g. »John Doe (john.doe@example.org)«.'));?>" /></p>
<p><label for="ldap_base_users"><?php p($l->t('Base User Tree'));?></label><textarea id="ldap_base_users" name="ldap_base_users" placeholder="<?php p($l->t('One User Base DN per line'));?>" data-default="<?php p($_['ldap_base_users_default']); ?>" title="<?php p($l->t('Base User Tree'));?>"></textarea></p>
<p><label for="ldap_attributes_for_user_search"><?php p($l->t('User Search Attributes'));?></label><textarea id="ldap_attributes_for_user_search" name="ldap_attributes_for_user_search" placeholder="<?php p($l->t('Optional; one attribute per line'));?>" data-default="<?php p($_['ldap_attributes_for_user_search_default']); ?>" title="<?php p($l->t('User Search Attributes'));?>"></textarea></p>
<p><label for="ldap_group_display_name"><?php p($l->t('Group Display Name Field'));?></label><input type="text" id="ldap_group_display_name" name="ldap_group_display_name" data-default="<?php p($_['ldap_group_display_name_default']); ?>" title="<?php p($l->t('The LDAP attribute to use to generate the groups\'s display name.'));?>" /></p>

View file

@ -0,0 +1,103 @@
<?php
/**
* @author Arthur Schiwon <blizzz@owncloud.com>
* @author Morris Jobke <hey@morrisjobke.de>
*
* @copyright Copyright (c) 2016, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
use OCA\user_ldap\lib\user\User;
use OCA\User_LDAP\Mapping\UserMapping;
use OCA\user_ldap\tests\integration\AbstractIntegrationTest;
require_once __DIR__ . '/../../../../../../lib/base.php';
class IntegrationTestUserDisplayName extends AbstractIntegrationTest {
/** @var UserMapping */
protected $mapping;
/**
* prepares the LDAP environment and sets up a test configuration for
* the LDAP backend.
*/
public function init() {
require(__DIR__ . '/../../setup-scripts/createExplicitUsers.php');
parent::init();
$this->mapping = new UserMapping(\OC::$server->getDatabaseConnection());
$this->mapping->clear();
$this->access->setUserMapper($this->mapping);
$userBackend = new OCA\user_ldap\USER_LDAP($this->access, \OC::$server->getConfig());
\OC_User::useBackend($userBackend);
}
/**
* adds a map entry for the user, so we know the username
*
* @param $dn
* @param $username
*/
private function prepareUser($dn, $username) {
// assigns our self-picked oc username to the dn
$this->mapping->map($dn, $username, 'fakeUUID-' . $username);
}
/**
* tests whether a display name consisting of two parts is created correctly
*
* @return bool
*/
protected function case1() {
$username = 'alice1337';
$dn = 'uid=alice,ou=Users,' . $this->base;
$this->prepareUser($dn, $username);
$displayName = \OC::$server->getUserManager()->get($username)->getDisplayName();
return strpos($displayName, '(Alice@example.com)') !== false;
}
/**
* tests whether a display name consisting of one part is created correctly
*
* @return bool
*/
protected function case2() {
$this->connection->setConfiguration([
'ldapUserDisplayName2' => '',
]);
$username = 'boris23421';
$dn = 'uid=boris,ou=Users,' . $this->base;
$this->prepareUser($dn, $username);
$displayName = \OC::$server->getUserManager()->get($username)->getDisplayName();
return strpos($displayName, '(Boris@example.com)') === false;
}
/**
* sets up the LDAP configuration to be used for the test
*/
protected function initConnection() {
parent::initConnection();
$this->connection->setConfiguration([
'ldapUserDisplayName' => 'displayName',
'ldapUserDisplayName2' => 'mail',
]);
}
}
require_once(__DIR__ . '/../../setup-scripts/config.php');
$test = new IntegrationTestUserDisplayName($host, $port, $adn, $apwd, $bdn);
$test->init();
$test->run();

View file

@ -63,6 +63,7 @@ foreach ($users as $uid) {
$entry['sn'] = $sn;
$entry['userPassword'] = $uid;
$entry['displayName'] = $sn . ', ' . $fn;
$entry['mail'] = $fn . '@example.com';
$ok = ldap_add($cr, $newDN, $entry);
if ($ok) {

View file

@ -749,7 +749,7 @@ class Test_User_User extends \Test\TestCase {
'markRefreshTime',
'updateQuota',
'updateEmail',
'storeDisplayName',
'composeAndStoreDisplayName',
'storeLDAPUserName',
'getHomePath',
'updateAvatar'
@ -894,4 +894,29 @@ class Test_User_User extends \Test\TestCase {
$user->getHomePath();
}
public function displayNameProvider() {
return [
['Roland Deschain', '', 'Roland Deschain'],
['Roland Deschain', null, 'Roland Deschain'],
['Roland Deschain', 'gunslinger@darktower.com', 'Roland Deschain (gunslinger@darktower.com)'],
];
}
/**
* @dataProvider displayNameProvider
*/
public function testComposeAndStoreDisplayName($part1, $part2, $expected) {
list($access, $config, $filesys, $image, $log, $avaMgr, , $userMgr) =
$this->getTestInstances();
$config->expects($this->once())
->method('setUserValue');
$user = new User(
'user', 'cn=user', $access, $config, $filesys, $image, $log, $avaMgr, $userMgr);
$displayName = $user->composeAndStoreDisplayName($part1, $part2);
$this->assertSame($expected, $displayName);
}
}

View file

@ -176,6 +176,11 @@ class USER_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
$this->access->connection->ldapUserDisplayName . '=*',
$this->access->getFilterPartForUserSearch($search)
));
$attrs = array($this->access->connection->ldapUserDisplayName, 'dn');
$additionalAttribute = $this->access->connection->ldapUserDisplayName2;
if(!empty($additionalAttribute)) {
$attrs[] = $additionalAttribute;
}
\OCP\Util::writeLog('user_ldap',
'getUsers: Options: search '.$search.' limit '.$limit.' offset '.$offset.' Filter: '.$filter,
@ -350,13 +355,30 @@ class USER_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
return $displayName;
}
//Check whether the display name is configured to have a 2nd feature
$additionalAttribute = $this->access->connection->ldapUserDisplayName2;
$displayName2 = '';
if(!empty($additionalAttribute)) {
$displayName2 = $this->access->readAttribute(
$this->access->username2dn($uid),
$additionalAttribute);
}
$displayName = $this->access->readAttribute(
$this->access->username2dn($uid),
$this->access->connection->ldapUserDisplayName);
if($displayName && (count($displayName) > 0)) {
$this->access->connection->writeToCache($cacheKey, $displayName[0]);
return $displayName[0];
$displayName = $displayName[0];
if(is_array($displayName2) && (count($displayName2) > 0)) {
$displayName2 = $displayName2[0];
}
$user = $this->access->userManager->get($uid);
$displayName = $user->composeAndStoreDisplayName($displayName, $displayName2);
$this->access->connection->writeToCache($cacheKey, $displayName);
return $displayName;
}
return null;