From 690a579a261a8479690b0b450a6e982274c97248 Mon Sep 17 00:00:00 2001 From: Christian Weiske Date: Tue, 7 Jan 2014 21:03:54 +0100 Subject: [PATCH] Implement request #301: Create users when using external auth login After a successful login with imap, smb or ftp, the corresponding user is created in an own database table. This is needed to make e.g. sharing files with this users work. The table may be used by several different external user authentication services. See the discussion in https://github.com/owncloud/apps/pull/1579 for details on the implementation design. --- appinfo/app.php | 1 + appinfo/database.xml | 57 ++++++++++++++++++ appinfo/version | 2 +- lib/base.php | 140 +++++++++++++++++++++++++++++++++++++++++++ lib/ftp.php | 8 +-- lib/imap.php | 8 +-- lib/smb.php | 6 +- 7 files changed, 207 insertions(+), 15 deletions(-) create mode 100644 appinfo/database.xml create mode 100644 lib/base.php diff --git a/appinfo/app.php b/appinfo/app.php index b7ae102..de6bb40 100644 --- a/appinfo/app.php +++ b/appinfo/app.php @@ -1,4 +1,5 @@ + + + *dbname* + true + false + + utf8 + + + + *dbprefix*users_external + + + + + backend + text + + true + 255 + + + + uid + text + + true + 64 + + + + displayname + text + + 64 + + + + users_unique + true + true + + uid + ascending + + + backend + ascending + + + + + +
+ +
diff --git a/appinfo/version b/appinfo/version index ceab6e1..1d71ef9 100644 --- a/appinfo/version +++ b/appinfo/version @@ -1 +1 @@ -0.1 \ No newline at end of file +0.3 \ No newline at end of file diff --git a/lib/base.php b/lib/base.php new file mode 100644 index 0000000..a8eb15b --- /dev/null +++ b/lib/base.php @@ -0,0 +1,140 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +/** + * Base class for external auth implementations that stores users + * on their first login in a local table. + * This is required for making many of the user-related owncloud functions + * work, including sharing files with them. + */ +abstract class OC_User_External_Base extends OC_User_Backend{ + protected $backend = ''; + + public function __construct($backend) { + $this->backend = $backend; + } + + /** + * @brief delete a user + * @param string $uid The username of the user to delete + * @return bool + * + * Deletes a user + */ + public function deleteUser($uid) { + $query = OC_DB::prepare('DELETE FROM `*PREFIX*users_external` WHERE `uid` = ? AND backend = ?'); + $query->execute(array($uid, $this->backend)); + return true; + } + + /** + * @brief get display name of the user + * @param $uid user ID of the user + * @return string display name + */ + public function getDisplayName($uid) { + $query = OC_DB::prepare('SELECT `displayname` FROM `*PREFIX*users_external` WHERE `uid` = ? AND backend = ?'); + $result = $query->execute(array($uid, $this->backend))->fetchAll(); + $displayName = trim($result[0]['displayname'], ' '); + if (!empty($displayName)) { + return $displayName; + } else { + return $uid; + } + } + + /** + * @brief Get a list of all display names + * @returns array with all displayNames (value) and the correspondig uids (key) + * + * Get a list of all display names and user ids. + */ + public function getDisplayNames($search = '', $limit = null, $offset = null) { + $displayNames = array(); + $query = OC_DB::prepare('SELECT `uid`, `displayname` FROM `*PREFIX*users_external`' + . ' WHERE (LOWER(`displayname`) LIKE LOWER(?) OR ' + . 'LOWER(`uid`) LIKE LOWER(?)) AND backend = ?', $limit, $offset); + $result = $query->execute(array($search . '%', $search . '%', $this->backend)); + $users = array(); + while ($row = $result->fetchRow()) { + $displayNames[$row['uid']] = $row['displayname']; + } + + return $displayNames; + } + + /** + * @brief Get a list of all users + * @returns array with all uids + * + * Get a list of all users. + */ + public function getUsers($search = '', $limit = null, $offset = null) { + $query = OC_DB::prepare('SELECT `uid` FROM `*PREFIX*users_external` WHERE LOWER(`uid`) LIKE LOWER(?) AND backend = ?', $limit, $offset); + $result = $query->execute(array($search . '%', $this->backend)); + $users = array(); + while ($row = $result->fetchRow()) { + $users[] = $row['uid']; + } + return $users; + } + + /** + * @return bool + */ + public function hasUserListings() { + return true; + } + + /** + * @brief Set display name + * @param $uid The username + * @param $displayName The new display name + * @returns true/false + * + * Change the display name of a user + */ + public function setDisplayName($uid, $displayName) { + if ($this->userExists($uid)) { + $query = OC_DB::prepare('UPDATE `*PREFIX*users_external` SET `displayname` = ? WHERE LOWER(`uid`) = ? AND backend = ?'); + $query->execute(array($displayName, $uid, $this->backend)); + return true; + } else { + return false; + } + } + + /** + * @brief Create user record in database + * @param $uid The username + * @returns void + */ + protected function storeUser($uid) + { + if (!$this->userExists($uid)) { + $query = OC_DB::prepare('INSERT INTO `*PREFIX*users_external` ( `uid`, `backend` ) VALUES( ?, ? )'); + $result = $query->execute(array($uid, $this->backend)); + } + } + + /** + * @brief check if a user exists + * @param string $uid the username + * @return boolean + */ + public function userExists($uid) { + $query = OC_DB::prepare('SELECT COUNT(*) FROM `*PREFIX*users_external` WHERE LOWER(`uid`) = LOWER(?) AND backend = ?'); + $result = $query->execute(array($uid, $this->backend)); + if (OC_DB::isError($result)) { + OC_Log::write('user_external', OC_DB::getErrorMessage($result), OC_Log::ERROR); + return false; + } + return $result->fetchOne() > 0; + } +} +?> diff --git a/lib/ftp.php b/lib/ftp.php index b94d7fe..35d9aa4 100644 --- a/lib/ftp.php +++ b/lib/ftp.php @@ -6,7 +6,7 @@ * See the COPYING-README file. */ -class OC_User_FTP extends OC_User_Backend{ +class OC_User_FTP extends OC_User_External_Base{ private $host; private $secure; private $protocol; @@ -18,6 +18,7 @@ class OC_User_FTP extends OC_User_Backend{ if($this->secure) { $this->protocol.='s'; } + parent::__construct($this->protocol . '://' . $this->host); } /** @@ -36,13 +37,10 @@ class OC_User_FTP extends OC_User_Backend{ $url = sprintf('%s://%s:%s@%s/', $this->protocol, $uid, $password, $this->host); $result=@opendir($url); if(is_resource($result)) { + $this->storeUser($uid); return $uid; }else{ return false; } } - - public function userExists($uid) { - return true; - } } diff --git a/lib/imap.php b/lib/imap.php index d1c6263..6a6fe23 100644 --- a/lib/imap.php +++ b/lib/imap.php @@ -6,10 +6,11 @@ * See the COPYING-README file. */ -class OC_User_IMAP extends OC_User_Backend{ +class OC_User_IMAP extends OC_User_External_Base { private $mailbox; public function __construct($mailbox) { + parent::__construct($mailbox); $this->mailbox=$mailbox; } @@ -31,13 +32,10 @@ class OC_User_IMAP extends OC_User_Backend{ imap_alerts(); if($mbox) { imap_close($mbox); + $this->storeUser($uid); return $uid; }else{ return false; } } - - public function userExists($uid) { - return true; - } } diff --git a/lib/smb.php b/lib/smb.php index 8a95120..d2bd5af 100644 --- a/lib/smb.php +++ b/lib/smb.php @@ -13,6 +13,7 @@ class OC_User_SMB extends OC_User_Backend{ const loginError='NT_STATUS_LOGON_FAILURE'; public function __construct($host) { + parent::__construct($host); $this->host=$host; } @@ -41,11 +42,8 @@ class OC_User_SMB extends OC_User_Backend{ OCP\Util::writeLog('user_external', 'ERROR: smbclient error: ' . trim($lastline), OCP\Util::ERROR); return false; } else { + $this->storeUser($uid); return $uid; } } - - public function userExists($uid) { - return true; - } } \ No newline at end of file