forked from dokuwiki/dokuwiki
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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.
- Loading branch information
Showing
8 changed files
with
147 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,9 @@ | |
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 @@ public function checkPass($user, $pass) { | |
* | ||
* @author Andreas Gohr <[email protected]> | ||
* @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; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -177,9 +177,10 @@ public function checkPass($user, $pass) { | |
* | ||
* @author James Van Lommel <[email protected]> | ||
* @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; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -146,9 +146,10 @@ public function checkPass($user, $pass) { | |
* @author Steffen Schoch <[email protected]> | ||
* | ||
* @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); | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 @@ public function checkPass($user, $pass) { | |
* @author Matthias Grimm <[email protected]> | ||
* | ||
* @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 @@ public function modifyUser($user, $changes) { | |
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 @@ protected function _addUserToGroup($user, $group, $force = false) { | |
$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 @@ protected function _delUserFromGroup($user, $group) { | |
$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 @@ protected function _addUser($user, $pwd, $name, $mail, $grps) { | |
} | ||
|
||
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 @@ protected function _delUser($user) { | |
$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 <[email protected]> | ||
* | ||
* @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 <[email protected]> | ||
* | ||
* @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 <[email protected]> | ||
* | ||
* @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 @@ protected function _delUser($user) { | |
* @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 @@ protected function _getUserInfo($user) { | |
* 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 <[email protected]> | ||
*/ | ||
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 @@ protected function _updateUserInfo($changes, $uid) { | |
$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; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -76,9 +76,10 @@ public function checkPass($user, $pass) { | |
* | ||
* @author Andreas Gohr <[email protected]> | ||
* @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; | ||
} | ||
|