summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Machniak <machniak@kolabsys.com>2014-11-04 13:47:08 (GMT)
committerAleksander Machniak <machniak@kolabsys.com>2014-11-04 13:47:08 (GMT)
commite561788b5c9bc243e332c09d86506489deeee796 (patch)
tree434c29987ad5515e6c967de4303c3f56c4d310ca
parentbe7ef6f18d07aa3f71be0184c8845c646fa09a18 (diff)
downloadkolab-wap-e561788b5c9bc243e332c09d86506489deeee796.tar.gz
Return user info in system.authenticate result for better performance (#3858)
-rw-r--r--lib/Auth.php10
-rw-r--r--lib/Auth/LDAP.php6
-rw-r--r--lib/User.php19
-rw-r--r--lib/ext/Net/LDAP3.php69
-rw-r--r--lib/kolab_api_controller.php38
-rw-r--r--lib/kolab_api_service.php4
-rw-r--r--lib/kolab_client_api.php7
-rw-r--r--lib/kolab_client_task.php9
8 files changed, 91 insertions, 71 deletions
diff --git a/lib/Auth.php b/lib/Auth.php
index 465f29d..88e9bb3 100644
--- a/lib/Auth.php
+++ b/lib/Auth.php
@@ -101,12 +101,14 @@ class Auth {
* This user is to be authenticated against the 'kolab'
* 'primary_domain'.
*
- * @param string $username User name (DN or mail)
- * @param string $password User password
+ * @param string $username User name (DN or mail)
+ * @param string $password User password
+ * @param string $domain User domain
+ * @param array $attributes List of result attributes
*
* @return bool|string User ID or False on failure
*/
- public function authenticate($username, $password, $domain = null)
+ public function authenticate($username, $password, $domain = null, &$attributes = null)
{
Log::info("Authentication request for $username against " . $this->domain);
@@ -116,7 +118,7 @@ class Auth {
// TODO: Debug logging for the use of a current or the creation of
// a new authentication class instance.
- $result = $this->_auth[$this->domain]->authenticate($username, $password, $domain);
+ $result = $this->_auth[$this->domain]->authenticate($username, $password, $domain, $attributes);
return $result;
}
diff --git a/lib/Auth/LDAP.php b/lib/Auth/LDAP.php
index a175fc8..d711c16 100644
--- a/lib/Auth/LDAP.php
+++ b/lib/Auth/LDAP.php
@@ -125,15 +125,15 @@ class LDAP extends Net_LDAP3 {
*
* @return bool|string User ID or False on failure
*/
- public function authenticate($username, $password, $domain = NULL)
+ public function authenticate($username, $password, $domain = null, &$attributes = null)
{
$this->_log(LOG_DEBUG, "Auth::LDAP: authentication request for $username against domain $domain");
- if ($domain == NULL) {
+ if (!$domain) {
$domain = $this->domain;
}
- $result = $this->login($username, $password, $domain);
+ $result = $this->login($username, $password, $domain, $attributes);
if (!$result) {
return false;
diff --git a/lib/User.php b/lib/User.php
index 1ef2f60..a248e57 100644
--- a/lib/User.php
+++ b/lib/User.php
@@ -35,17 +35,16 @@ class User
private $working_domain;
- public function authenticate($username, $password, $domain = null, $method = false)
+ public function authenticate($username, $password, $domain = null, &$attributes = null)
{
- //console("Running with domain", $domain);
-
if (empty($domain)) {
$this->auth = Auth::get_instance();
- } else {
+ }
+ else {
$this->auth = Auth::get_instance($domain);
}
- $result = $this->auth->authenticate($username, $password);
+ $result = $this->auth->authenticate($username, $password, $domain, $attributes);
if ($result) {
$this->_authenticated = true;
@@ -57,13 +56,17 @@ class User
// set unique attribute value as userid
if ($this->userid != 'cn=Directory Manager') {
$unique_attr = kolab_api_service::unique_attribute();
- if ($result = $this->auth->get_entry_attribute($result, $unique_attr)) {
- $this->userid = $result;
+
+ if ($attributes && $attributes[$unique_attr]) {
+ $this->userid = $attributes[$unique_attr];
+ }
+ else if ($uid = $this->auth->get_entry_attribute($result, $unique_attr)) {
+ $this->userid = $uid;
}
}
}
- return $this->_authenticated;
+ return $result;
}
public function authenticated()
diff --git a/lib/ext/Net/LDAP3.php b/lib/ext/Net/LDAP3.php
index 86c6310..64c46d8 100644
--- a/lib/ext/Net/LDAP3.php
+++ b/lib/ext/Net/LDAP3.php
@@ -1011,7 +1011,7 @@ class Net_LDAP3
return $replica_hosts;
}
- public function login($username, $password, $domain = null)
+ public function login($username, $password, $domain = null, &$attributes = null)
{
$this->_debug("Net_LDAP3::login(\$username = '" . $username . "', \$password = '****', \$domain = '" . $domain . "')");
@@ -1045,6 +1045,12 @@ class Net_LDAP3
return null;
}
+ // fetch user attributes if requested
+ if (!empty($attributes)) {
+ $attributes = $this->get_entry($entry_dn, $attributes);
+ $attributes = self::normalize_entry($attributes, true);
+ }
+
return $entry_dn;
}
@@ -1092,7 +1098,7 @@ class Net_LDAP3
$this->_debug("Net::LDAP3::login() actual filter: " . $filter);
- $result = $this->search($base_dn, $filter, 'sub');
+ $result = $this->search($base_dn, $filter, 'sub', $attributes);
if (!$result) {
$this->_debug("Could not search $base_dn with $filter");
@@ -1108,9 +1114,8 @@ class Net_LDAP3
return null;
}
- $entries = $result->entries();
- $entry = self::normalize_result($entries);
- $entry_dn = key($entry);
+ $entries = $result->entries(true);
+ $entry_dn = key($entries);
$bound = $this->bind($entry_dn, $password);
@@ -1119,6 +1124,11 @@ class Net_LDAP3
return null;
}
+ // replace attributes list with key-value data
+ if (!empty($attributes)) {
+ $attributes = $entries[$entry_dn];
+ }
+
return $entry_dn;
}
@@ -1690,10 +1700,11 @@ class Net_LDAP3
* Turn an LDAP entry into a regular PHP array with attributes as keys.
*
* @param array $entry Attributes array as retrieved from ldap_get_attributes() or ldap_get_entries()
+ * @param bool $flat Convert one-element-array values into strings
*
* @return array Hash array with attributes as keys
*/
- public static function normalize_entry($entry)
+ public static function normalize_entry($entry, $flat = false)
{
$rec = array();
for ($i=0; $i < $entry['count']; $i++) {
@@ -1701,6 +1712,10 @@ class Net_LDAP3
for ($j=0; $j < $entry[$attr]['count']; $j++) {
$rec[$attr][$j] = $entry[$attr][$j];
}
+
+ if ($flat && count($rec[$attr]) == 1) {
+ $rec[$attr] = $rec[$attr][0];
+ }
}
return $rec;
@@ -1718,34 +1733,19 @@ class Net_LDAP3
$result = array();
for ($x = 0; $x < $_result['count']; $x++) {
- $dn = $_result[$x]['dn'];
- $result[$dn] = array();
- for ($y = 0; $y < $_result[$x]['count']; $y++) {
- $attr = $_result[$x][$y];
- if ($_result[$x][$attr]['count'] == 1) {
- switch ($attr) {
- case 'objectclass':
- $result[$dn][$attr] = array(strtolower($_result[$x][$attr][0]));
- break;
- default:
- $result[$dn][$attr] = $_result[$x][$attr][0];
- break;
- }
+ $dn = $_result[$x]['dn'];
+ $entry = self::normalize_entry($_result[$x], true);
+
+ if (!empty($entry['objectclass'])) {
+ if (is_array($entry['objectclass'])) {
+ $entry['objectclass'] = array_map('strtolower', $entry['objectclass']);
}
else {
- $result[$dn][$attr] = array();
- for ($z = 0; $z < $_result[$x][$attr]['count']; $z++) {
- switch ($attr) {
- case 'objectclass':
- $result[$dn][$attr][] = strtolower($_result[$x][$attr][$z]);
- break;
- default:
- $result[$dn][$attr][] = $_result[$x][$attr][$z];
- break;
- }
- }
+ $entry['objectclass'] = strtolower($entry['objectclass']);
}
}
+
+ $result[$dn] = $entry;
}
return $result;
@@ -1756,16 +1756,15 @@ class Net_LDAP3
switch ($scope) {
case 2:
return 'sub';
- break;
+
case 1:
return 'one';
- break;
+
case 0:
return 'base';
- break;
+
default:
$this->_debug("Scope $scope is not a valid scope integer");
- break;
}
}
@@ -1780,7 +1779,7 @@ class Net_LDAP3
{
switch ($scope) {
case 'sub':
- $function = $ns_function = 'ldap_search';
+ $function = $ns_function = 'ldap_search';
break;
case 'base':
$function = $ns_function = 'ldap_read';
diff --git a/lib/kolab_api_controller.php b/lib/kolab_api_controller.php
index db7a842..ed716cf 100644
--- a/lib/kolab_api_controller.php
+++ b/lib/kolab_api_controller.php
@@ -293,8 +293,6 @@ class kolab_api_controller
{
Log::trace("Authenticating user: " . $postdata['username']);
- $valid = false;
-
// destroy old session
if ($this->session_validate($postdata)) {
session_destroy();
@@ -303,38 +301,50 @@ class kolab_api_controller
session_start();
$_SESSION['user'] = new User();
+ $attributes = null;
+ $password = $postdata['password'];
+ $username = $postdata['username'];
+ $domain = $postdata['domain'];
- if (empty($postdata['domain'])) {
+ // find user domain
+ if (empty($domain)) {
Log::debug("No login domain specified. Attempting to derive from username.");
- if (count(explode('@', $postdata['username'])) > 1) {
- $login = explode('@', $postdata['username']);
+ if (count(explode('@', $username)) == 2) {
+ $login = explode('@', $username);
$username = array_shift($login);
- $domain = array_shift($login);
+ $domain = array_shift($login);
}
else {
Log::debug("No domain name space in the username, using the primary domain");
$domain = $this->config->get('kolab', 'primary_domain');
}
}
- else {
- $domain = $postdata['domain'];
- }
- if (empty($username)) {
- $username = $postdata['username'];
+ // user info requested (it's not possible to get manager info)
+ if ($postdata['info'] && ($username != 'cn=Directory Manager')) {
+ $service = $this->get_service('user');
+ $attributes = $service->object_attributes('user');
}
- $valid = $_SESSION['user']->authenticate($username, $postdata['password'], $domain);
+ // authenticate
+ $user_dn = $_SESSION['user']->authenticate($username, $password, $domain, $attributes);
// start new (PHP) session
- if ($valid) {
+ if ($user_dn) {
$_SESSION['time'] = time();
- return array(
+ $result = array(
'user' => $_SESSION['user']->get_username(),
'userid' => $_SESSION['user']->get_userid(),
'domain' => $_SESSION['user']->get_domain(),
'session_token' => session_id(),
);
+
+ if (!empty($attributes)) {
+ $attributes = array($user_dn => $attributes);
+ $result['info'] = $service->parse_result_attributes('user', $attributes);
+ }
+
+ return $result;
}
return false;
diff --git a/lib/kolab_api_service.php b/lib/kolab_api_service.php
index e881a78..9cd37de 100644
--- a/lib/kolab_api_service.php
+++ b/lib/kolab_api_service.php
@@ -469,7 +469,7 @@ abstract class kolab_api_service
*
* @return array Entry attributes
*/
- protected function parse_result_attributes($object_name, $attrs = array())
+ public function parse_result_attributes($object_name, $attrs = array())
{
if (empty($attrs) || !is_array($attrs)) {
return $attrs;
@@ -549,7 +549,7 @@ abstract class kolab_api_service
*
* @return array Entry attributes
*/
- protected function object_attributes($object_name)
+ public function object_attributes($object_name)
{
$unique_attr = self::unique_attribute();
$object_types = $this->object_types($object_name);
diff --git a/lib/kolab_client_api.php b/lib/kolab_client_api.php
index af9eeca..8b205c2 100644
--- a/lib/kolab_client_api.php
+++ b/lib/kolab_client_api.php
@@ -95,15 +95,18 @@ class kolab_client_api
*
* @param string $username User name
* @param string $password User password
+ * @param string $domain User domain
+ * @param bool $get_info Request user info in result
*
* @return kolab_client_api_result Request response
*/
- public function login($username, $password, $domain = null)
+ public function login($username, $password, $domain = null, $get_info = false)
{
$query = array(
'username' => $username,
'password' => $password,
- 'domain' => $domain
+ 'domain' => $domain,
+ 'info' => $get_info ? 1 : 0,
);
$response = $this->post('system.authenticate', null, $query);
diff --git a/lib/kolab_client_task.php b/lib/kolab_client_task.php
index 87d8b62..da0acf5 100644
--- a/lib/kolab_client_task.php
+++ b/lib/kolab_client_task.php
@@ -202,7 +202,7 @@ class kolab_client_task
$login = $this->get_input('login', 'POST');
if ($login['username']) {
- $result = $this->api->login($login['username'], $login['password'], $login['domain']);
+ $result = $this->api->login($login['username'], $login['password'], $login['domain'], true);
if ($token = $result->get('session_token')) {
$user = array(
@@ -219,8 +219,11 @@ class kolab_client_task
$user['fullname'] = ucwords($m[1]);
}
else {
- $res = $this->api->get('user.info', array('id' => $user['id']));
- $res = $res->get();
+ $res = $result->get('info');
+ if (empty($res)) {
+ $res = $this->api->get('user.info', array('id' => $user['id']));
+ $res = $res->get();
+ }
if (is_array($res) && !empty($res)) {
$user['language'] = $res['preferredlanguage'];