lib/Auth lib/Auth.php lib/ext lib/kolab_api_controller.php lib/kolab_api_service.php lib/kolab_client_api.php lib/kolab_client_task.php lib/User.php

Aleksander Machniak machniak at kolabsys.com
Tue Nov 4 18:29:20 CET 2014


 lib/Auth.php                 |   10 +++---
 lib/Auth/LDAP.php            |    6 +--
 lib/User.php                 |   19 ++++++-----
 lib/ext/Net/LDAP3.php        |   69 +++++++++++++++++++++----------------------
 lib/kolab_api_controller.php |   38 ++++++++++++++---------
 lib/kolab_api_service.php    |    4 +-
 lib/kolab_client_api.php     |    7 +++-
 lib/kolab_client_task.php    |    9 +++--
 8 files changed, 91 insertions(+), 71 deletions(-)

New commits:
commit e561788b5c9bc243e332c09d86506489deeee796
Author: Aleksander Machniak <machniak at kolabsys.com>
Date:   Tue Nov 4 08:47:08 2014 -0500

    Return user info in system.authenticate result for better performance (#3858)

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'];




More information about the commits mailing list