* @copyright 2015 Damien Regad * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html * @version 1.1 * @link https://github.com/dregad/dokuwiki-authwordpress */ // must be run within Dokuwiki if(!defined('DOKU_INC')) die(); /** * WordPress password hashing framework */ require_once('class-phpass.php'); /** * Authentication class */ class auth_plugin_authwordpress extends DokuWiki_Auth_Plugin { /** * SQL statement to retrieve User data from WordPress DB * (including group memberships) * '%prefix%' will be replaced by the actual prefix (from plugin config) */ protected $sql_wp_user_data = "SELECT id, user_login, user_pass, user_email, display_name, meta_value AS groups FROM %prefix%users u JOIN %prefix%usermeta m ON u.id = m.user_id AND meta_key = '%prefix%capabilities'"; /** * Wordpress database connection */ protected $db; /** * Users cache */ protected $users; /** * True if all users have been loaded in the cache * @see $users */ protected $usersCached = false; /** * Constructor. */ public function __construct() { parent::__construct(); $this->cando['getUsers'] = true; // Try to establish a connection to the WordPress DB // abort in case of failure try { $this->wp_connect(); } catch (Exception $e) { msg(sprintf($this->getLang('error_connect_failed'), $e->getMessage())); $this->success = false; return; } // Initialize SQL query with configured prefix $this->sql_wp_user_data = str_replace( '%prefix%', $this->getConf('prefix'), $this->sql_wp_user_data ); $this->success = true; } /** * Check user+password * * @param string $user the user name * @param string $pass the clear text password * @return bool * * @uses PasswordHash::CheckPassword WordPress password hasher */ public function checkPass($user, $pass) { $data = $this->getUserData($user); if ($data === false) { return false; } $hasher = new PasswordHash(8, true); $check = $hasher->CheckPassword($pass, $data['pass']); dbglog("Password " . ($check ? 'OK' : 'Invalid')); return $check; } /** * Bulk retrieval of user data * * @param int $start index of first user to be returned * @param int $limit max number of users to be returned * @param array $filter array of field/pattern pairs * @return array userinfo (refer getUserData for internal userinfo details) */ public function retrieveUsers($start = 0, $limit = 0, $filter = array()) { msg($this->getLang('user_list_use_wordpress')); if($filter) { msg($this->getLang('error_filters_unsupported')); } $this->cacheAllUsers(); return $this->users; } /** * Returns info about the given user * * @param string $user the user name * @return array containing user data or false */ public function getUserData($user, $requireGroups=true) { if(isset($this->users[$user])) { return $this->users[$user]; } $sql = $this->sql_wp_user_data . 'WHERE user_login = :user'; $stmt = $this->db->prepare($sql); $stmt->bindParam(':user', $user); dbglog("Retrieving data for user '$user'\n$sql"); if (!$stmt->execute()) { // Query execution failed $err = $stmt->errorInfo(); dbglog("Error $err[1]: $err[2]"); return false; } $user = $stmt->fetch(PDO::FETCH_ASSOC); if ($user === false) { // Unknown user dbglog("Unknown user"); return false; } return $this->cacheUser($user); } /** * Connect to Wordpress database * Initializes $db property as PDO object */ protected function wp_connect() { if($this->db) { // Already connected return; } // Build connection string $dsn = array( 'host=' . $this->getConf('hostname'), 'dbname=' . $this->getConf('database'), ); $port = $this->getConf('port'); if ($port) { $dsn[] = 'port=' . $port; } $dsn = 'mysql:' . implode(';', $dsn); $this->db = new PDO($dsn, $this->getConf('username'), $this->getConf('password')); } /** * Convert a Wordpress DB User row to DokuWiki user info array * and stores it in the users cache * * @param array $user Raw Wordpress user table row * @return array user data */ protected function cacheUser($row) { global $conf; $login = $row['user_login']; // If the user is already cached, just return it if(isset($this->users[$login])) { return $this->users[$login]; } // Group membership - add DokuWiki's default group $groups = array_keys(unserialize($row['groups'])); if($this->getConf('usedefaultgroup')) { $groups[] = $conf['defaultgroup']; } $info = array( 'user' => $login, 'name' => $row['display_name'], 'pass' => $row['user_pass'], 'mail' => $row['user_email'], 'grps' => $groups, ); $this->users[$login] = $info; return $info; } /** * Loads all Wordpress users into the cache * * @return void */ protected function cacheAllUsers() { if($this->usersCached) { return; } $stmt = $this->db->prepare($this->sql_wp_user_data); $stmt->execute(); foreach($stmt->fetchAll(PDO::FETCH_ASSOC) as $user) { $this->cacheUser($user); } $this->usersCached = true; } } // vim:ts=4:sw=4:noet: