diff --git a/inc/auth.php b/inc/auth.php index 7ae0da1a41ec92d3d23938716ce56cb77cdfa4f2..69ff930be433cc5a2a756b38a2709d0bc1ad510c 100644 --- a/inc/auth.php +++ b/inc/auth.php @@ -51,7 +51,7 @@ // do the login either by cookie or provided credentials if($conf['useacl']){ // external trust mechanism in place? - if(!is_null($auth) && $auth->canDo('trustExternal')){ + if(!is_null($auth) && $auth->canDo('external')){ $auth->trustExternal($_REQUEST['u'],$_REQUEST['p'],$_REQUEST['r']); }else{ auth_login($_REQUEST['u'],$_REQUEST['p'],$_REQUEST['r']); @@ -413,7 +413,7 @@ function register(){ global $auth; if(!$_POST['save']) return false; - if(!$auth->canDo('createUser')) return false; + if(!$auth->canDo('addUser')) return false; //clean username $_POST['login'] = preg_replace('/.*:/','',$_POST['login']); @@ -483,8 +483,8 @@ function updateprofile() { if(!$_POST['save']) return false; - // should not be able to get here without modifyUser being possible... - if(!$auth->canDo('modifyUser')) { + // should not be able to get here without Profile being possible... + if(!$auth->canDo('Profile')) { msg($lang['profna'],-1); return false; } @@ -543,11 +543,11 @@ function act_resendpwd(){ if(!$_POST['save']) return false; if(!$conf['resendpasswd']) return false; - // should not be able to get here without modifyUser being possible... - if(!$auth->canDo('modifyUser')) { + // should not be able to get here without modPass being possible... + if(!$auth->canDo('modPass')) { msg($lang['resendna'],-1); return false; - } + } if (empty($_POST['login'])) { msg($lang['resendpwdmissing'], -1); diff --git a/inc/auth/basic.class.php b/inc/auth/basic.class.php index 9ea1a598bcfff55c4c05cfadae21e347afd93abf..7f187d4584387758ac3ef08b51e95837d792f130 100644 --- a/inc/auth/basic.class.php +++ b/inc/auth/basic.class.php @@ -12,22 +12,88 @@ class auth_basic { var $success = true; + /** - * Constructor + * Posible things an auth backend module may be able to + * do. The things a backend can do need to be set to true + * in the constructor. + */ + var $cando = array ( + 'addUser' => false, // can Users be created? + 'delUser' => false, // can Users be deleted? + 'modLogin' => false, // can login names be changed? + 'modPass' => false, // can passwords be changed? + 'modName' => false, // can real names be changed? + 'modMail' => false, // can emails be changed? + 'modGroups' => false, // can groups be changed? + 'getUsers' => false, // can a (filtered) list of users be retrieved? + 'getUserCount'=> false, // can the number of users be retrieved? + 'getGroups' => false, // can a list of available groups be retrieved? + 'external' => false, // does the module do external auth checking? + ); + + + /** + * Constructor. * * Carry out sanity checks to ensure the object is - * able to operate. + * able to operate. Set capabilities in $this->cando + * array here * * Set $this->success to false if checks fail * * @author Christopher Smith <chris@jalakai.co.uk> */ -# function auth_basic() { -# } + function auth_basic() { + // the base class constructor does nothing, derived class + // constructors do the real work + } + + /** + * Capability check. [ DO NOT OVERRIDE ] + * + * Checks the capabilities set in the $this->cando array and + * some pseudo capabilities (shortcutting access to multiple + * ones) + * + * ususal capabilities start with lowercase letter + * shortcut capabilities start with uppercase letter + * + * @author Andreas Gohr <andi@splitbrain.org> + * @return bool + */ + function canDo($cap) { + switch($cap){ + case 'Profile': + // can at least one of the user's properties be changed? + return ( $this->cando['modPass'] || + $this->cando['modName'] || + $this->cando['modMail'] ); + break; + case 'UserMod': + // can at least anything be changed? + return ( $this->cando['modPass'] || + $this->cando['modName'] || + $this->cando['modMail'] || + $this->cando['modLogin'] || + $this->cando['modGroups'] || + $this->cando['modMail'] ); + break; + default: + // print a helping message for developers + if(!isset($this->cando[$cap])){ + msg("Check for unknown capability '$cap' - Do you use an outdated Plugin?",-1); + } + return $this->cando[$cap]; + } + } + /** * Do all authentication [ OPTIONAL ] * + * Set $this->cando['external'] = true when implemented + * * If this function is implemented it will be used to * authenticate a user - all other DokuWiki internals * will not be used for authenticating, thus @@ -55,7 +121,9 @@ class auth_basic { * @param bool $sticky Cookie should not expire * @return bool true on successful auth */ -# function trustExternal($user,$pass,$sticky=false){ + function trustExternal($user,$pass,$sticky=false){ +# // some example: +# # global $USERINFO; # global $conf; # $sticky ? $sticky = true : $sticky = false; //sanity check @@ -71,18 +139,7 @@ class auth_basic { # $_SESSION[$conf['title']]['auth']['pass'] = $pass; # $_SESSION[$conf['title']]['auth']['info'] = $USERINFO; # return true; -# } - - /** - * Check if authorisation mechanism supports fn and - * that fn will operate in the current environment - * - * @author Christopher Smith <chris@jalakai.co.uk> - * @return bool - */ - function canDo($fn) { - return method_exists($this, $fn); - } + } /** * Check user+password [ MUST BE OVERRIDDEN ] @@ -94,7 +151,6 @@ class auth_basic { * @return bool */ function checkPass($user,$pass){ - msg("no valid authorisation system in use", -1); return false; } @@ -113,9 +169,8 @@ class auth_basic { * @return array containing user data or false */ function getUserData($user) { - - msg("no valid authorisation system in use", -1); - return false; + msg("no valid authorisation system in use", -1); + return false; } /** @@ -128,106 +183,97 @@ class auth_basic { * The new user HAS TO be added to the default group by this * function! * + * Set addUser capability when implemented + * * @author Andreas Gohr <andi@splitbrain.org> */ -# function createUser($user,$pass,$name,$mail,$grps=null){ -# -# msg("authorisation method does not allow creation of new users", -1); -# return null; -# } + function createUser($user,$pass,$name,$mail,$grps=null){ + msg("authorisation method does not allow creation of new users", -1); + return null; + } /** * Modify user data [implement only where required/possible] * + * Set the mod* capabilities according to the implemented features + * * @author Chris Smith <chris@jalakai.co.uk> * @param $user nick of the user to be changed * @param $changes array of field/value pairs to be changed (password will be clear text) * @return bool */ -# function modifyUser($user, $changes) { -# msg("authorisation method does not allow modifying of user data", -1); -# return false; -# } + function modifyUser($user, $changes) { + msg("authorisation method does not allow modifying of user data", -1); + return false; + } /** * Delete one or more users [implement only where required/possible] * + * Set delUser capability when implemented + * * @author Chris Smith <chris@jalakai.co.uk> * @param array $users * @return int number of users deleted */ -# function deleteUsers($users) { -# msg("authorisation method does not allow deleting of users", -1); -# return false; -# } + function deleteUsers($users) { + msg("authorisation method does not allow deleting of users", -1); + return false; + } /** * Return a count of the number of user which meet $filter criteria * [should be implemented whenever retrieveUsers is implemented] * + * Set getUserCount capability when implemented + * * @author Chris Smith <chris@jalakai.co.uk> */ -# function getUserCount($filter=array()) { -# -# msg("authorisation method does not provide user counts", -1); -# return 0; -# } + function getUserCount($filter=array()) { + msg("authorisation method does not provide user counts", -1); + return 0; + } /** * Bulk retrieval of user data [implement only where required/possible] * + * Set getUsers capability when implemented + * * @author Chris Smith <chris@jalakai.co.uk> * @param start index of first user to be returned * @param limit max number of users to be returned * @param filter array of field/pattern pairs, null for no filter * @return array of userinfo (refer getUserData for internal userinfo details) */ -# function retrieveUsers($start=0,$limit=-1,$filter=null) { -# msg("authorisation method does not support mass retrieval of user data", -1); -# return array(); -# } + function retrieveUsers($start=0,$limit=-1,$filter=null) { + msg("authorisation method does not support mass retrieval of user data", -1); + return array(); + } /** * Define a group [implement only where required/possible] * + * Set addGroup capability when implemented + * * @author Chris Smith <chris@jalakai.co.uk> * @return bool */ -# function addGroup($group) { -# msg("authorisation method does not support independent group creation", -1); -# return false; -# } + function addGroup($group) { + msg("authorisation method does not support independent group creation", -1); + return false; + } /** * Retrieve groups [implement only where required/possible] * + * Set getGroups capability when implemented + * * @author Chris Smith <chris@jalakai.co.uk> * @return array */ -# function retrieveGroups($start=0,$limit=0) { -# msg("authorisation method does not support group list retrieval", -1); -# return array(); -# } - - /** - * Give user membership of a group [implement only where required/possible] - * - * @author Chris Smith <chris@jalakai.co.uk> - * @return bool - */ -# function joinGroup($user, $group) { -# msg("authorisation method does not support alteration of group memberships", -1); -# return false; -# } + function retrieveGroups($start=0,$limit=0) { + msg("authorisation method does not support group list retrieval", -1); + return array(); + } - /** - * Remove user from a group [implement only where required/possible] - * - * @author Chris Smith <chris@jalakai.co.uk> - * @return bool - */ -# function leaveGroup($user, $group) { -# msg("authorisation method does not support alteration of group memberships", -1); -# return false; -# } } diff --git a/inc/auth/ldap.class.php b/inc/auth/ldap.class.php index f59800476ca6811e4474abe77968c075926d6690..de1c8570b8c8665f2b0b15ad7c3c7eb9427287dc 100644 --- a/inc/auth/ldap.class.php +++ b/inc/auth/ldap.class.php @@ -20,8 +20,13 @@ class auth_ldap extends auth_basic { global $conf; $this->cnf = $conf['auth']['ldap']; if(empty($this->cnf['groupkey'])) $this->cnf['groupkey'] = 'cn'; - } + // try to connect + if(!$this->_openLDAP()) $this->success = false; + + // auth_ldap currently just handles authentication, so no + // capabilities are set + } /** * Check user+password diff --git a/inc/auth/mysql.class.php b/inc/auth/mysql.class.php index fb7f43d802c2686431a6b70fcb8b88ea1b6041ce..0fb311e26d5a241d8c998273ddf6cdc379d7dcf9 100644 --- a/inc/auth/mysql.class.php +++ b/inc/auth/mysql.class.php @@ -42,76 +42,62 @@ class auth_mysql extends auth_basic { $this->cnf = $conf['auth']['mysql']; $this->defaultgroup = $conf['defaultgroup']; - } - /** - * Check if authorisation mechanism supports fn and - * that fn will operate in the current environment - * - * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net> - * @author Christopher Smith <chris@jalakai.co.uk> - * @return bool - */ - function canDo($fn) { - $wop = false; /* function is write operation */ - - /* general database configuration set? */ + // set capabilities based upon config strings set if (empty($this->cnf['server']) || empty($this->cnf['user']) || empty($this->cnf['password']) || empty($this->cnf['database'])) - return false; - - switch($fn) { - case 'checkPass': - $config = array('checkPass'); - break; - case 'getUserData': - $config = array('getUserInfo','getGroups'); - break; - case 'createUser': - $config = array('getUserInfo','getGroups','addUser', - 'getUserID','addGroup','addUserGroup','delGroup'); - $wop = true; - break; - case 'modifyUser': - $config = array('getUserID','updateUser','UpdateTarget', - 'getGroups','getGroupID','addGroup','addUserGroup', - 'delGroup','getGroupID','delUserGroup'); - $wop = true; - break; - case 'deleteUsers': - $config = array('getUserID','delUser','delUserRefs'); - $wop = true; - break; - case 'getUserCount': - $config = array('getUsers'); - break; - case 'retrieveUsers': - $config = array('getUsers','getUserInfo','getGroups'); - break; - case 'joinGroup': - $config = array('getUserID','getGroupID','addGroup', - 'addUserGroup','delGroup'); - $wop = true; - break; - case 'leaveGroup': - $config = array('getUserID','getGroupID','delUserGroup'); - $wop = true; - break; - default: - return false; /* unknown function call */ + return; + + $this->cando['addUser'] = $this->_chkcnf(array('getUserInfo', + 'getGroups', + 'addUser', + 'getUserID', + 'addGroup', + 'addUserGroup'),true); + $this->cando['delUser'] = $this->_chkcnf(array('getUserID', + 'delUser', + 'delUserRefs'),true); + $this->cando['modLogin'] = $this->_chkcnf(array('getUserID', + 'updateUser', + 'UpdateTarget', + 'getGroups', + 'getGroupID', + 'addGroup', + 'addUserGroup', + 'delGroup', + 'getGroupID', + 'delUserGroup'),true); + $this->cando['modPass'] = $this->cando['modLogin']; + $this->cando['modName'] = $this->cando['modLogin']; + $this->cando['modMail'] = $this->cando['modLogin']; + $this->cando['modGroups'] = $this->cando['modLogin']; + $this->cando['getGroups'] = $this->_chkcnf(array('getGroups', + 'getGroupID'),false); + $this->cando['getUsers'] = $this->_chkcnf(array('getUsers', + 'getUserInfo', + 'getGroups'),false); + $this->cando['getUserCount'] = $this->_chkcnf(array('getUsers'),false); + } + + /** + * Check if the given config strings are set + * + * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net> + * @return bool + */ + function _chkcnf($keys, $wop=false){ + foreach ($keys as $key){ + if (empty($this->cnf[$key])) return false; } - + /* write operation and lock array filled with tables names? */ - if ($wop && (!is_array($this->cnf['TablesToLock']) || empty($this->cnf['TablesToLock']))) + if ($wop && (!is_array($this->cnf['TablesToLock']) || + !count($this->cnf['TablesToLock']))){ return false; - - foreach ($config as $statement) - if (empty($this->cnf[$statement])) - return false; /* required statement not set */ + } - /* all tests passed :-) */ return true; - } + } /** * Checks if the given user exists and the given plaintext password diff --git a/inc/auth/plain.class.php b/inc/auth/plain.class.php index 373bb2907ca4570c968d08b9442cee6a9946e1b8..2dae8de984a66e007db521928f698cb241ddb946 100644 --- a/inc/auth/plain.class.php +++ b/inc/auth/plain.class.php @@ -25,37 +25,28 @@ class auth_plain extends auth_basic { * Constructor * * Carry out sanity checks to ensure the object is - * able to operate. + * able to operate. Set capabilities. * - * Set $this->success to false if checks fail - * * @author Christopher Smith <chris@jalakai.co.uk> */ function auth_plain() { - if (!@is_readable(AUTH_USERFILE)) $this->success = false; + if (!@is_readable(AUTH_USERFILE)){ + $this->success = false; + }else{ + if(@is_writable(AUTH_USERFILE)){ + $this->cando['addUser'] = true; + $this->cando['delUser'] = true; + $this->cando['modLogin'] = true; + $this->cando['modPass'] = true; + $this->cando['modName'] = true; + $this->cando['modMail'] = true; + $this->cando['modGroups'] = true; + } + $this->cando['getUsers'] = true; + $this->cando['getUserCount'] = true; + } } - /** - * Check if authorisation mechanism supports fn and - * that fn will operate in the current environment - * - * @author Christopher Smith <chris@jalakai.co.uk> - * @return bool - */ - function canDo($fn) { - - switch ($fn) { - case 'createUser' : - case 'modifyUser' : - case 'deleteUsers' : - case 'joinGroup' : - case 'leaveGroup' : - return (@is_writable(AUTH_USERFILE)); - } - - return method_exists($this, $fn); - } - /** * Check user+password [required auth function] * @@ -264,40 +255,6 @@ class auth_plain extends auth_basic { return $out; } - /** - * Give user membership of a group - * - * @author Chris Smith <chris@jalakai.co.uk> - * @return bool - */ - function joinGroup($user, $group) { - - // sanity checks, user must exist, and not currently a group member - if (($userinfo = $this->getUserData($user)) === false) return false; - if (in_array($group, $userinfo['grps'])) return true; - - $userinfo['grps'][] = $group; - - return $this->modifyUser($user, array('grps' => $userinfo['grps'])); - } - - /** - * Remove user from a group - * - * @author Chris Smith <chris@jalakai.co.uk> - * @return bool - */ - function leaveGroup($user, $group) { - - // sanity checks, user must exist, and currently be a group member - if (($userinfo = $this->getUserData($user)) === false) return false; - if (($i = array_search($group, $userinfo['grps'])) === false) return true; - - array_splice($userinfo['grps'],$i,1); - - return $this->modifyUser($user, array('grps' => $userinfo['grps'])); - } - /** * Load all user data * diff --git a/inc/html.php b/inc/html.php index e53dcbaf61a3023275a84ca7f61f6fb7d660d1cf..c641dc21214886cdfde0935f7c1edd00ec2f5dc5 100644 --- a/inc/html.php +++ b/inc/html.php @@ -73,14 +73,14 @@ function html_login(){ </fieldset> </form> <?php - if($conf['openregister']){ + if($auth->canDo('addUser') && $conf['openregister']){ print '<p>'; print $lang['reghere']; print ': <a href="'.wl($ID,'do=register').'" class="wikilink1">'.$lang['register'].'</a>'; print '</p>'; } - if ($auth->canDo('modifyUser') && $conf['resendpasswd']) { + if ($auth->canDo('modPass') && $conf['resendpasswd']) { print '<p>'; print $lang['pwdforget']; print ': <a href="'.wl($ID,'do=resendpwd').'" class="wikilink1">'.$lang['btn_resendpwd'].'</a>'; @@ -872,6 +872,7 @@ function html_updateprofile(){ global $conf; global $ID; global $INFO; + global $auth; print p_locale_xhtml('updateprofile'); @@ -891,12 +892,14 @@ function html_updateprofile(){ </label><br /> <label class="block"> <?php echo $lang['fullname']?> - <input type="text" name="fullname" class="edit" size="50" value="<?php echo formText($_POST['fullname'])?>" /> + <input type="text" name="fullname" <?php if(!$auth->canDo('modName')) echo 'disabled="disabled"'?> class="edit" size="50" value="<?php echo formText($_POST['fullname'])?>" /> </label><br /> <label class="block"> <?php echo $lang['email']?> - <input type="text" name="email" class="edit" size="50" value="<?php echo formText($_POST['email'])?>" /> + <input type="text" name="email" <?php if(!$auth->canDo('modName')) echo 'disabled="disabled"'?> class="edit" size="50" value="<?php echo formText($_POST['email'])?>" /> </label><br /><br /> + + <?php if($auth->canDo('modPass')) { ?> <label class="block"> <?php echo $lang['newpass']?> <input type="password" name="newpass" class="edit" size="50" /> @@ -905,6 +908,7 @@ function html_updateprofile(){ <?php echo $lang['passchk']?> <input type="password" name="passchk" class="edit" size="50" /> </label><br /> + <?php } ?> <?php if ($conf['profileconfirm']) { ?> <br /> diff --git a/inc/template.php b/inc/template.php index e9aba3297c414580182b5dd165117c833ef47043..3e9cd55ad19a9cf6f0e0ba38f18d3442ed32891d 100644 --- a/inc/template.php +++ b/inc/template.php @@ -358,7 +358,7 @@ function tpl_button($type){ print html_btn('backlink',$ID,'',array('do' => 'backlink')); break; case 'profile': - if(($_SERVER['REMOTE_USER']) && $auth->canDo('modifyUser') && ($ACT!='profile')){ + if(($_SERVER['REMOTE_USER']) && $auth->canDo('Profile') && ($ACT!='profile')){ print html_btn('profile',$ID,'',array('do' => 'profile')); } break; @@ -466,7 +466,7 @@ function tpl_actionlink($type,$pre='',$suf=''){ tpl_link(wl($ID,'do=backlink'),$pre.$lang['btn_backlink'].$suf, 'class="action backlink"'); break; case 'profile': - if(($_SERVER['REMOTE_USER']) && $auth->canDo('modifyUser') && ($ACT!='profile')){ + if(($_SERVER['REMOTE_USER']) && $auth->canDo('Profile') && ($ACT!='profile')){ tpl_link(wl($ID,'do=profile'),$pre.$lang['btn_profile'].$suf, 'class="action profile"'); } break; diff --git a/lib/plugins/usermanager/admin.php b/lib/plugins/usermanager/admin.php index d96fbfb6d82391b897598ff8b27126e385d3cb42..8ba4472ac53a81f9a259d7cb0626abe31699e05a 100644 --- a/lib/plugins/usermanager/admin.php +++ b/lib/plugins/usermanager/admin.php @@ -40,7 +40,7 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { if (!isset($auth)) { $this->disabled = $this->lang['noauth']; - } else if (!$auth->canDo('retrieveUsers')) { + } else if (!$auth->canDo('getUsers')) { $this->disabled = $this->lang['notsupported']; } else { @@ -103,8 +103,8 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { } if ($cmd != "search") { - if (!empty($_REQUEST['start'])) - $this->_start = $_REQUEST['start']; + if (!empty($_REQUEST['start'])) + $this->_start = $_REQUEST['start']; $this->_filter = $this->_retrieveFilter(); } @@ -145,15 +145,15 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { $users = array_keys($user_list); $page_buttons = $this->_pagination(); - $delete_disable = $this->_auth->canDo('deleteUsers') ? '' : 'disabled="disabled"'; + $delete_disable = $this->_auth->canDo('delUser') ? '' : 'disabled="disabled"'; - if ($this->_auth->canDo('modifyUser')) { - $edit_disable = ''; - $img_useredit = 'user_edit.png'; - } else { - $edit_disable = 'disabled="disabled"'; - $img_useredit = 'no_user_edit.png'; - } + if ($this->_auth->canDo('UserMod')) { + $edit_disable = ''; + $img_useredit = 'user_edit.png'; + } else { + $edit_disable = 'disabled="disabled"'; + $img_useredit = 'no_user_edit.png'; + } print $this->locale_xhtml('intro'); print $this->locale_xhtml('list'); @@ -220,7 +220,7 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { $style = $this->_edit_user ? " style=\"width: 46%; float: left;\"" : ""; - if ($this->_auth->canDo('createUser')) { + if ($this->_auth->canDo('addUser')) { ptln("<div".$style.">"); print $this->locale_xhtml('add'); ptln(" <div class=\"level2\">"); @@ -231,7 +231,7 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { ptln("</div>"); } - if($this->_edit_user && $this->_auth->canDo('modifyUser')){ + if($this->_edit_user && $this->_auth->canDo('UserMod')){ ptln("<div".$style." id=\"scroll__here\">"); print $this->locale_xhtml('edit'); ptln(" <div class=\"level2\">"); @@ -243,6 +243,10 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { } } + + /** + * @todo disable fields which the backend can't change + */ function _htmlUserForm($cmd,$user=null,$indent=0) { if ($user) { @@ -300,7 +304,7 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { function _addUser(){ - if (!$this->_auth->canDo('createUser')) return false; + if (!$this->_auth->canDo('addUser')) return false; list($user,$pass,$name,$mail,$grps) = $this->_retrieveUser(); if (empty($user)) return false; @@ -313,7 +317,7 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { */ function _deleteUser(){ - if (!$this->_auth->canDo('deleteUsers')) return false; + if (!$this->_auth->canDo('delUser')) return false; $selected = $_REQUEST['delete']; if (!is_array($selected) || empty($selected)) return false; @@ -334,7 +338,7 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { * Modify user */ function _modifyUser(){ - if (!$this->_auth->canDo('modifyUser')) return false; + if (!$this->_auth->canDo('UserMod')) return false; list($user,$pass,$name,$mail,$grps) = $this->_retrieveUser(); if (empty($user)) return false;