summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Smith <chris@jalakai.co.uk>2014-03-12 15:38:28 +0000
committerChristopher Smith <chris@jalakai.co.uk>2014-03-12 17:47:43 +0000
commit2046a6546c8ed62b9a7b33305b6201458f2f8291 (patch)
tree47fda0d8608fd1c96d9db755feef8a0d8dc9b4f8
parentd397e6da631cb6d262ad14ec7b46b75d1b60fbcf (diff)
downloadrpg-2046a6546c8ed62b9a7b33305b6201458f2f8291.tar.gz
rpg-2046a6546c8ed62b9a7b33305b6201458f2f8291.tar.bz2
Allow user info to be retrieved without groups
Some parts of dokuwiki (e.g. recent changes, old revisions) can requests lots of user info (to provide editor names) without requiring any group information. This change also implements caching of user info by authmysql & authpgsql plugins to avoid repeated querying of the DB to retrieve the same user information.
-rw-r--r--inc/auth.php6
-rw-r--r--inc/common.php2
-rw-r--r--lib/plugins/auth.php6
-rw-r--r--lib/plugins/authad/auth.php3
-rw-r--r--lib/plugins/authldap/auth.php3
-rw-r--r--lib/plugins/authmysql/auth.php147
-rw-r--r--lib/plugins/authpgsql/auth.php8
-rw-r--r--lib/plugins/authplain/auth.php3
8 files changed, 147 insertions, 31 deletions
diff --git a/inc/auth.php b/inc/auth.php
index 2bdc3eb00..cbdd7163b 100644
--- a/inc/auth.php
+++ b/inc/auth.php
@@ -922,7 +922,7 @@ function auth_sendPassword($user, $password) {
if(!$auth) return false;
$user = $auth->cleanUser($user);
- $userinfo = $auth->getUserData($user);
+ $userinfo = $auth->getUserData($user, DokuWiki_Auth_Plugin::IGNORE_GROUPS);
if(!$userinfo['mail']) return false;
@@ -1184,7 +1184,7 @@ function act_resendpwd() {
}
$user = io_readfile($tfile);
- $userinfo = $auth->getUserData($user);
+ $userinfo = $auth->getUserData($user, DokuWiki_Auth_Plugin::IGNORE_GROUPS);
if(!$userinfo['mail']) {
msg($lang['resendpwdnouser'], -1);
return false;
@@ -1236,7 +1236,7 @@ function act_resendpwd() {
$user = trim($auth->cleanUser($INPUT->post->str('login')));
}
- $userinfo = $auth->getUserData($user);
+ $userinfo = $auth->getUserData($user, DokuWiki_Auth_Plugin::IGNORE_GROUPS);
if(!$userinfo['mail']) {
msg($lang['resendpwdnouser'], -1);
return false;
diff --git a/inc/common.php b/inc/common.php
index 9fbebde94..6851cdea3 100644
--- a/inc/common.php
+++ b/inc/common.php
@@ -1467,7 +1467,7 @@ function editorinfo($username) {
case 'username':
case 'email':
case 'email_link':
- if($auth) $info = $auth->getUserData($username);
+ if($auth) $info = $auth->getUserData($username, DokuWiki_Auth_Plugin::IGNORE_GROUPS);
break;
default:
return hsc($username);
diff --git a/lib/plugins/auth.php b/lib/plugins/auth.php
index b04735639..f9e5cded9 100644
--- a/lib/plugins/auth.php
+++ b/lib/plugins/auth.php
@@ -15,6 +15,9 @@ if(!defined('DOKU_INC')) die();
class DokuWiki_Auth_Plugin extends DokuWiki_Plugin {
public $success = true;
+ const IGNORE_GROUPS = false;
+ const REQUIRE_GROUPS = true;
+
/**
* Possible things an auth backend module may be able to
* do. The things a backend can do need to be set to true
@@ -234,9 +237,10 @@ class DokuWiki_Auth_Plugin extends DokuWiki_Plugin {
*
* @author Andreas Gohr <andi@splitbrain.org>
* @param string $user the user name
+ * @param bool $requireGroups whether or not the returned data must include groups
* @return array containing user data or false
*/
- public function getUserData($user) {
+ public function getUserData($user, $requireGroups=true) {
if(!$this->cando['external']) msg("no valid authorisation system in use", -1);
return false;
}
diff --git a/lib/plugins/authad/auth.php b/lib/plugins/authad/auth.php
index 0860e5756..a3119dda6 100644
--- a/lib/plugins/authad/auth.php
+++ b/lib/plugins/authad/auth.php
@@ -177,9 +177,10 @@ class auth_plugin_authad extends DokuWiki_Auth_Plugin {
*
* @author James Van Lommel <james@nosq.com>
* @param string $user
+ * @param bool $requireGroups (optional) - ignored, groups are always supplied by this plugin
* @return array
*/
- public function getUserData($user) {
+ public function getUserData($user, $requireGroups=true) {
global $conf;
global $lang;
global $ID;
diff --git a/lib/plugins/authldap/auth.php b/lib/plugins/authldap/auth.php
index 9d03afd7f..eaa2d160a 100644
--- a/lib/plugins/authldap/auth.php
+++ b/lib/plugins/authldap/auth.php
@@ -146,9 +146,10 @@ class auth_plugin_authldap extends DokuWiki_Auth_Plugin {
* @author Steffen Schoch <schoch@dsb.net>
*
* @param string $user
+ * @param bool $requireGroups (optional) - ignored, groups are always supplied by this plugin
* @return array containing user data or false
*/
- public function getUserData($user) {
+ public function getUserData($user, $requireGroups=true) {
return $this->_getUserData($user);
}
diff --git a/lib/plugins/authmysql/auth.php b/lib/plugins/authmysql/auth.php
index 1e6e6a4a9..774fce01f 100644
--- a/lib/plugins/authmysql/auth.php
+++ b/lib/plugins/authmysql/auth.php
@@ -21,6 +21,9 @@ class auth_plugin_authmysql extends DokuWiki_Auth_Plugin {
/** @var int database subrevision */
protected $dbsub = 0;
+ /** @var array cache to avoid re-reading user info data */
+ protected $cacheUserInfo = array();
+
/**
* Constructor
*
@@ -174,12 +177,18 @@ class auth_plugin_authmysql extends DokuWiki_Auth_Plugin {
* @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
*
* @param string $user user login to get data for
+ * @param bool $requireGroups when true, group membership information should be included in the returned array;
+ * when false, it maybe included, but is not required by the caller
* @return array|bool
*/
- public function getUserData($user) {
+ public function getUserData($user, $requireGroups=true) {
+ if($this->_cacheExists($user, $requireGroups)) {
+ return $this->cacheUserInfo[$user];
+ }
+
if($this->_openDB()) {
$this->_lockTables("READ");
- $info = $this->_getUserInfo($user);
+ $info = $this->_getUserInfo($user, $requireGroups);
$this->_unlockTables();
$this->_closeDB();
} else
@@ -262,21 +271,23 @@ class auth_plugin_authmysql extends DokuWiki_Auth_Plugin {
if($this->_openDB()) {
$this->_lockTables("WRITE");
- if(($uid = $this->_getUserID($user))) {
- $rc = $this->_updateUserInfo($changes, $uid);
+ $rc = $this->_updateUserInfo($user, $changes);
- if($rc && isset($changes['grps']) && $this->cando['modGroups']) {
- $groups = $this->_getGroups($user);
- $grpadd = array_diff($changes['grps'], $groups);
- $grpdel = array_diff($groups, $changes['grps']);
+ if($rc && isset($changes['grps']) && $this->cando['modGroups']) {
+ $groups = $this->_getGroups($user);
+ $grpadd = array_diff($changes['grps'], $groups);
+ $grpdel = array_diff($groups, $changes['grps']);
- foreach($grpadd as $group)
- if(($this->_addUserToGroup($user, $group, 1)) == false)
- $rc = false;
+ foreach($grpadd as $group) {
+ if(($this->_addUserToGroup($user, $group, 1)) == false) {
+ $rc = false;
+ }
+ }
- foreach($grpdel as $group)
- if(($this->_delUserFromGroup($user, $group)) == false)
- $rc = false;
+ foreach($grpdel as $group) {
+ if(($this->_delUserFromGroup($user, $group)) == false) {
+ $rc = false;
+ }
}
}
@@ -466,7 +477,10 @@ class auth_plugin_authmysql extends DokuWiki_Auth_Plugin {
$sql = str_replace('%{user}', $this->_escape($user), $sql);
$sql = str_replace('%{gid}', $this->_escape($gid), $sql);
$sql = str_replace('%{group}', $this->_escape($group), $sql);
- if($this->_modifyDB($sql) !== false) return true;
+ if($this->_modifyDB($sql) !== false) {
+ $this->_flushUserInfoCache($user);
+ return true;
+ }
if($newgroup) { // remove previously created group on error
$sql = str_replace('%{gid}', $this->_escape($gid), $this->getConf('delGroup'));
@@ -501,6 +515,10 @@ class auth_plugin_authmysql extends DokuWiki_Auth_Plugin {
$sql = str_replace('%{gid}', $this->_escape($gid), $sql);
$sql = str_replace('%{group}', $this->_escape($group), $sql);
$rc = $this->_modifyDB($sql) == 0 ? true : false;
+
+ if ($rc) {
+ $this->_flushUserInfoCache($user);
+ }
}
}
return $rc;
@@ -590,6 +608,7 @@ class auth_plugin_authmysql extends DokuWiki_Auth_Plugin {
}
if($gid !== false){
+ $this->_flushUserInfoCache($user);
return true;
} else {
/* remove the new user and all group relations if a group can't
@@ -626,16 +645,96 @@ class auth_plugin_authmysql extends DokuWiki_Auth_Plugin {
$sql = str_replace('%{uid}', $this->_escape($uid), $this->getConf('delUser'));
$sql = str_replace('%{user}', $this->_escape($user), $sql);
$this->_modifyDB($sql);
+ $this->_flushUserInfoCache($user);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Flush cached user information
+ *
+ * @author Christopher Smith <chris@jalakai.co.uk>
+ *
+ * @param string $user username of the user whose data is to be removed from the cache
+ * if null, empty the whole cache
+ * @return none
+ */
+ protected function _flushUserInfoCache($user=null) {
+ if (is_null($user)) {
+ $this->cacheUserInfo = array();
+ } else {
+ unset($this->cacheUserInfo[$user]);
+ }
+ }
+
+ /**
+ * Quick lookup to see if a user's information has been cached
+ *
+ * This test does not need a database connection or read lock
+ *
+ * @author Christopher Smith <chris@jalakai.co.uk>
+ *
+ * @param string $user username to be looked up in the cache
+ * @param bool $requireGroups true, if cached info should include group memberships
+ *
+ * @return bool existence of required user information in the cache
+ */
+ protected function _cacheExists($user, $requireGroups=true) {
+ if (isset($this->cacheUserInfo[$user])) {
+ if (!is_array($this->cacheUserInfo[$user])) {
+ return true; // user doesn't exist
+ }
+
+ if (!$requireGroups || isset($this->cacheUserInfo[$user]['grps'])) {
return true;
}
}
+
return false;
}
/**
- * getUserInfo
+ * Get a user's information
+ *
+ * The database connection must already be established for this function to work.
+ *
+ * @author Christopher Smith <chris@jalakai.co.uk>
+ *
+ * @param string $user username of the user whose information is being reterieved
+ * @param bool $requireGroups true if group memberships should be included
+ * @param bool $useCache true if ok to return cached data & to cache returned data
+ *
+ * @return mixed false|array false if the user doesn't exist
+ * array containing user information if user does exist
+ */
+ protected function _getUserInfo($user, $requireGroups=true, $useCache=true) {
+ $info = null;
+
+ if ($useCache && isset($this->cacheUserInfo[$user])) {
+ $info = $this->cacheUserInfo[$user];
+ }
+
+ if (is_null($info)) {
+ $info = $this->_retrieveUserInfo($user);
+ }
+
+ if ($requireGroups && $info && !isset($info['grps'])) {
+ $info['grps'] = $this->_getGroups($user);
+ }
+
+ if ($useCache) {
+ $this->cacheUserInfo[$user] = $info;
+ }
+
+ return $info;
+ }
+
+ /**
+ * retrieveUserInfo
*
- * Gets the data for a specific user The database connection
+ * Gets the data for a specific user. The database connection
* must already be established for this function to work.
* Otherwise it will return 'false'.
*
@@ -644,12 +743,11 @@ class auth_plugin_authmysql extends DokuWiki_Auth_Plugin {
* @param string $user user's nick to get data for
* @return bool|array false on error, user info on success
*/
- protected function _getUserInfo($user) {
+ protected function _retrieveUserInfo($user) {
$sql = str_replace('%{user}', $this->_escape($user), $this->getConf('getUserInfo'));
$result = $this->_queryDB($sql);
if($result !== false && count($result)) {
$info = $result[0];
- $info['grps'] = $this->_getGroups($user);
return $info;
}
return false;
@@ -666,20 +764,26 @@ class auth_plugin_authmysql extends DokuWiki_Auth_Plugin {
* The database connection has already to be established for this
* function to work. Otherwise it will return 'false'.
*
- * The password will be crypted if necessary.
+ * The password will be encrypted if necessary.
*
+ * @param string $user user's nick being updated
* @param array $changes array of items to change as pairs of item and value
* @param mixed $uid user id of dataset to change, must be unique in DB
* @return bool true on success or false on error
*
* @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
*/
- protected function _updateUserInfo($changes, $uid) {
+ protected function _updateUserInfo($user, $changes) {
$sql = $this->getConf('updateUser')." ";
$cnt = 0;
$err = 0;
if($this->dbcon) {
+ $uid = $this->_getUserID($user);
+ if ($uid === false) {
+ return false;
+ }
+
foreach($changes as $item => $value) {
if($item == 'user') {
if(($this->_getUserID($changes['user']))) {
@@ -707,6 +811,7 @@ class auth_plugin_authmysql extends DokuWiki_Auth_Plugin {
$sql .= " ".str_replace('%{uid}', $uid, $this->getConf('UpdateTarget'));
if(get_class($this) == 'auth_mysql') $sql .= " LIMIT 1"; //some PgSQL inheritance comp.
$this->_modifyDB($sql);
+ $this->_flushUserInfoCache($user);
}
return true;
}
diff --git a/lib/plugins/authpgsql/auth.php b/lib/plugins/authpgsql/auth.php
index e51b39858..99f3ed443 100644
--- a/lib/plugins/authpgsql/auth.php
+++ b/lib/plugins/authpgsql/auth.php
@@ -160,7 +160,7 @@ class auth_plugin_authpgsql extends auth_plugin_authmysql {
$result = $this->_queryDB($sql);
foreach($result as $user)
- if(($info = $this->_getUserInfo($user['user'])))
+ if(($info = $this->_getCachedUserInfo($user['user'])))
$out[$user['user']] = $info;
$this->_unlockTables();
@@ -212,7 +212,10 @@ class auth_plugin_authpgsql extends auth_plugin_authmysql {
$sql = str_replace('%{user}', addslashes($user), $sql);
$sql = str_replace('%{gid}', addslashes($gid), $sql);
$sql = str_replace('%{group}', addslashes($group), $sql);
- if($this->_modifyDB($sql) !== false) return true;
+ if($this->_modifyDB($sql) !== false) {
+ $this->_flushUserInfoCache($user);
+ return true;
+ }
if($newgroup) { // remove previously created group on error
$sql = str_replace('%{gid}', addslashes($gid), $this->conf['delGroup']);
@@ -267,6 +270,7 @@ class auth_plugin_authpgsql extends auth_plugin_authmysql {
}
if($gid !== false){
+ $this->_flushUserInfoCache($user);
return true;
} else {
/* remove the new user and all group relations if a group can't
diff --git a/lib/plugins/authplain/auth.php b/lib/plugins/authplain/auth.php
index 8c4ce0dd9..16ecaa147 100644
--- a/lib/plugins/authplain/auth.php
+++ b/lib/plugins/authplain/auth.php
@@ -76,9 +76,10 @@ class auth_plugin_authplain extends DokuWiki_Auth_Plugin {
*
* @author Andreas Gohr <andi@splitbrain.org>
* @param string $user
+ * @param bool $requireGroups (optional) ignored by this plugin, grps info always supplied
* @return array|bool
*/
- public function getUserData($user) {
+ public function getUserData($user, $requireGroups=true) {
if($this->users === null) $this->_loadUserData();
return isset($this->users[$user]) ? $this->users[$user] : false;
}