From ee0f1490e1872cbe6071f5758e292ae1646ab1af Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 21 Jun 2011 19:28:46 +0200 Subject: [PATCH] Multiply changes to user system keeping tracked of the logged in user is no longer done by the active backend but by oc_user directly instead multiply backends can be active at the same time, allowing alternative authentication procedures like openid or tokens to be used next to the regular user system --- lib/User/backend.php | 68 ++++++++++++----------------- lib/User/database.php | 97 +++++++++--------------------------------- lib/base.php | 2 +- lib/user.php | 99 ++++++++++++++++++++++++++++++++++--------- 4 files changed, 127 insertions(+), 139 deletions(-) diff --git a/lib/User/backend.php b/lib/User/backend.php index e99016a521..8ea7f78190 100644 --- a/lib/User/backend.php +++ b/lib/User/backend.php @@ -21,7 +21,10 @@ * */ - +/** + * error code for functions not provided by the storage provider + */ +define('OC_USER_BACKEND_NOT_IMPLEMENTED',-501); /** * abstract base class for user management @@ -37,7 +40,9 @@ abstract class OC_USER_BACKEND { * Creates a new user. Basic checking of username is done in OC_USER * itself, not in its subclasses. */ - public static function createUser($uid, $password){} + public function createUser($uid, $password){ + return OC_USER_BACKEND_NOT_IMPLEMENTED; + } /** * @brief delete a user @@ -46,41 +51,9 @@ abstract class OC_USER_BACKEND { * * Deletes a user */ - public static function deleteUser( $uid ){} - - /** - * @brief Try to login a user - * @param $uid The username of the user to log in - * @param $password The password of the user - * @returns true/false - * - * Log in a user - if the password is ok - */ - public static function login($uid, $password){} - - /** - * @brief Kick the user - * @returns true - * - * Logout, destroys session - */ - public static function logout(){} - - /** - * @brief Check if the user is logged in - * @returns true/false - * - * Checks if the user is logged in - */ - public static function isLoggedIn(){} - - /** - * @brief Autogenerate a password - * @returns string - * - * generates a password - */ - public static function generatePassword(){} + public function deleteUser( $uid ){ + return OC_USER_BACKEND_NOT_IMPLEMENTED; + } /** * @brief Set password @@ -90,7 +63,9 @@ abstract class OC_USER_BACKEND { * * Change the password of a user */ - public static function setPassword($uid, $password){} + public function setPassword($uid, $password){ + return OC_USER_BACKEND_NOT_IMPLEMENTED; + } /** * @brief Check if the password is correct @@ -100,7 +75,9 @@ abstract class OC_USER_BACKEND { * * Check if the password is correct without logging in the user */ - public static function checkPassword($uid, $password){} + public function checkPassword($uid, $password){ + return OC_USER_BACKEND_NOT_IMPLEMENTED; + } /** * @brief Get a list of all users @@ -108,5 +85,16 @@ abstract class OC_USER_BACKEND { * * Get a list of all users. */ - public static function getUsers(){} + public function getUsers(){ + return OC_USER_BACKEND_NOT_IMPLEMENTED; + } + + /** + * @brief check if a user exists + * @param string $uid the username + * @return boolean + */ + public function userExists($uid){ + return OC_USER_BACKEND_NOT_IMPLEMENTED; + } } diff --git a/lib/User/database.php b/lib/User/database.php index eeabb592c2..0396ac3095 100644 --- a/lib/User/database.php +++ b/lib/User/database.php @@ -50,12 +50,8 @@ class OC_USER_DATABASE extends OC_USER_BACKEND { * Creates a new user. Basic checking of username is done in OC_USER * itself, not in its subclasses. */ - public static function createUser( $uid, $password ){ - // Check if the user already exists - $query = OC_DB::prepare( "SELECT * FROM `*PREFIX*users` WHERE uid = ?" ); - $result = $query->execute( array( $uid )); - - if ( $result->numRows() > 0 ){ + public function createUser( $uid, $password ){ + if( $this->userExists($uid) ){ return false; } else{ @@ -73,76 +69,13 @@ class OC_USER_DATABASE extends OC_USER_BACKEND { * * Deletes a user */ - public static function deleteUser( $uid ){ + public function deleteUser( $uid ){ // Delete user-group-relation $query = OC_DB::prepare( "DELETE FROM `*PREFIX*users` WHERE uid = ?" ); $result = $query->execute( array( $uid )); return true; } - /** - * @brief Try to login a user - * @param $uid The username of the user to log in - * @param $password The password of the user - * @returns true/false - * - * Log in a user - if the password is ok - */ - public static function login( $uid, $password ){ - // Query - $query = OC_DB::prepare( "SELECT uid FROM *PREFIX*users WHERE uid = ? AND password = ?" ); - $result = $query->execute( array( $uid, sha1( $password ))); - - if( $result->numRows() > 0 ){ - // Set username if name and password are known - $row = $result->fetchRow(); - $_SESSION['user_id'] = $row["uid"]; - OC_LOG::add( "core", $_SESSION['user_id'], "login" ); - return true; - } - else{ - return false; - } - } - - /** - * @brief Kick the user - * @returns true - * - * Logout, destroys session - */ - public static function logout(){ - OC_LOG::add( "core", $_SESSION['user_id'], "logout" ); - $_SESSION['user_id'] = false; - - return true; - } - - /** - * @brief Check if the user is logged in - * @returns true/false - * - * Checks if the user is logged in - */ - public static function isLoggedIn() { - if( isset($_SESSION['user_id']) AND $_SESSION['user_id'] ){ - return true; - } - else{ - return false; - } - } - - /** - * @brief Autogenerate a password - * @returns string - * - * generates a password - */ - public static function generatePassword(){ - return uniqId(); - } - /** * @brief Set password * @param $uid The username @@ -151,12 +84,8 @@ class OC_USER_DATABASE extends OC_USER_BACKEND { * * Change the password of a user */ - public static function setPassword( $uid, $password ){ - // Check if the user already exists - $query = OC_DB::prepare( "SELECT * FROM `*PREFIX*users` WHERE uid = ?" ); - $result = $query->execute( array( $uid )); - - if( $result->numRows() > 0 ){ + public function setPassword( $uid, $password ){ + if( $this->userExists($uid) ){ $query = OC_DB::prepare( "UPDATE *PREFIX*users SET password = ? WHERE uid = ?" ); $result = $query->execute( array( sha1( $password ), $uid )); @@ -175,7 +104,7 @@ class OC_USER_DATABASE extends OC_USER_BACKEND { * * Check if the password is correct without logging in the user */ - public static function checkPassword( $uid, $password ){ + public function checkPassword( $uid, $password ){ $query = OC_DB::prepare( "SELECT uid FROM *PREFIX*users WHERE uid = ? AND password = ?" ); $result = $query->execute( array( $uid, sha1( $password ))); @@ -193,7 +122,7 @@ class OC_USER_DATABASE extends OC_USER_BACKEND { * * Get a list of all users. */ - public static function getUsers(){ + public function getUsers(){ $query = OC_DB::prepare( "SELECT uid FROM *PREFIX*users" ); $result = $query->execute(); @@ -203,4 +132,16 @@ class OC_USER_DATABASE extends OC_USER_BACKEND { } return $users; } + + /** + * @brief check if a user exists + * @param string $uid the username + * @return boolean + */ + public function userExists($uid){ + $query = OC_DB::prepare( "SELECT * FROM `*PREFIX*users` WHERE uid = ?" ); + $result = $query->execute( array( $uid )); + + return $result->numRows() > 0; + } } diff --git a/lib/base.php b/lib/base.php index 1baf5dc167..e93c471272 100644 --- a/lib/base.php +++ b/lib/base.php @@ -93,7 +93,7 @@ require_once('search.php'); $error=(count(OC_UTIL::checkServer())>0); -OC_USER::setBackend( OC_CONFIG::getValue( "userbackend", "database" )); +OC_USER::useBackend( OC_CONFIG::getValue( "userbackend", "database" )); OC_GROUP::setBackend( OC_CONFIG::getValue( "groupbackend", "database" )); // Set up file system unless forbidden diff --git a/lib/user.php b/lib/user.php index 09501e59c5..2e11a30e85 100644 --- a/lib/user.php +++ b/lib/user.php @@ -40,7 +40,7 @@ if( !OC_CONFIG::getValue( "installed", false )){ */ class OC_USER { // The backend used for user management - private static $_backend = null; + private static $_usedBackends = array(); // Backends available (except database) private static $_backends = array(); @@ -66,15 +66,25 @@ class OC_USER { public static function getBackends(){ return self::$_backends; } + + /** + * @brief gets used backends + * @returns array of backends + * + * Returns the names of all used backends. + */ + public static function getUsedBackends(){ + return array_keys(self::$_usedBackends); + } /** - * @brief Sets the backend + * @brief Adds the backend to the list of used backends * @param $backend default: database The backend to use for user managment * @returns true/false * * Set the User Authentication Module */ - public static function setBackend( $backend = 'database' ){ + public static function useBackend( $backend = 'database' ){ // You'll never know what happens if( null === $backend OR !is_string( $backend )){ $backend = 'database'; @@ -86,11 +96,11 @@ class OC_USER { case 'mysql': case 'sqlite': require_once('User/database.php'); - self::$_backend = new OC_USER_DATABASE(); + self::$_usedBackends[$backend] = new OC_USER_DATABASE(); break; default: $className = 'OC_USER_' . strToUpper($backend); - self::$_backend = new $className(); + self::$_usedBackends[$backend] = new $className(); break; } @@ -119,7 +129,7 @@ class OC_USER { return false; } // Check if user already exists - if( in_array( $uid, self::getUsers())){ + if( self::userExists($uid) ){ return false; } @@ -127,13 +137,17 @@ class OC_USER { $run = true; OC_HOOK::emit( "OC_USER", "pre_createUser", array( "run" => &$run, "uid" => $uid, "password" => $password )); - if( $run && self::$_backend->createUser( $uid, $password )){ - OC_HOOK::emit( "OC_USER", "post_createUser", array( "uid" => $uid, "password" => $password )); - return true; - } - else{ - return false; + if( $run ){ + //create the user in the first backend that supports creating users + foreach(self::$_usedBackends as $backend){ + $result=$backend->createUser($uid,$password); + if($result!==OC_USER_BACKEND_NOT_IMPLEMENTED){ + OC_HOOK::emit( "OC_USER", "post_createUser", array( "uid" => $uid, "password" => $password )); + return true; + } + } } + return false; } /** @@ -147,7 +161,11 @@ class OC_USER { $run = true; OC_HOOK::emit( "OC_USER", "pre_deleteUser", array( "run" => &$run, "uid" => $uid )); - if( $run && self::$_backend->deleteUser( $uid )){ + if( $run ){ + //delete the user from all backends + foreach(self::$_usedBackends as $backend){ + $backend->deleteUser($uid); + } // We have to delete the user from all groups foreach( OC_GROUP::getUserGroups( $uid ) as $i ){ OC_GROUP::removeFromGroup( $uid, $i ); @@ -174,7 +192,9 @@ class OC_USER { $run = true; OC_HOOK::emit( "OC_USER", "pre_login", array( "run" => &$run, "uid" => $uid )); - if( $run && self::$_backend->login( $uid, $password )){ + if( $run && self::checkPassword( $uid, $password )){ + $_SESSION['user_id'] = $uid; + OC_LOG::add( "core", $_SESSION['user_id'], "login" ); OC_HOOK::emit( "OC_USER", "post_login", array( "uid" => $uid )); return true; } @@ -191,7 +211,9 @@ class OC_USER { */ public static function logout(){ OC_HOOK::emit( "OC_USER", "logout", array()); - return self::$_backend->logout(); + OC_LOG::add( "core", $_SESSION['user_id'], "logout" ); + $_SESSION['user_id'] = false; + return true; } /** @@ -201,7 +223,12 @@ class OC_USER { * Checks if the user is logged in */ public static function isLoggedIn(){ - return self::$_backend->isLoggedIn(); + if( isset($_SESSION['user_id']) AND $_SESSION['user_id'] ){ + return true; + } + else{ + return false; + } } /** @@ -211,7 +238,7 @@ class OC_USER { * generates a password */ public static function generatePassword(){ - return substr( md5( uniqId().time()), 0, 10 ); + return uniqId(); } /** @@ -226,7 +253,12 @@ class OC_USER { $run = true; OC_HOOK::emit( "OC_USER", "pre_setPassword", array( "run" => &$run, "uid" => $uid, "password" => $password )); - if( $run && self::$_backend->setPassword( $uid, $password )){ + if( $run ){ + foreach(self::$_usedBackends as $backend){ + if($backend->userExists($uid)){ + $backend->setPassword($uid,$password); + } + } OC_HOOK::emit( "OC_USER", "post_setPassword", array( "uid" => $uid, "password" => $password )); return true; } @@ -244,7 +276,12 @@ class OC_USER { * Check if the password is correct without logging in the user */ public static function checkPassword( $uid, $password ){ - return self::$_backend->checkPassword( $uid, $password ); + foreach(self::$_usedBackends as $backend){ + $result=$backend->checkPassword( $uid, $password ); + if($result===true){ + return true; + } + } } /** @@ -254,6 +291,28 @@ class OC_USER { * Get a list of all users. */ public static function getUsers(){ - return self::$_backend->getUsers(); + $users=array(); + foreach(self::$_usedBackends as $backend){ + $result=$backend->getUsers(); + if($result!=OC_USER_BACKEND_NOT_IMPLEMENTED){ + $users=array_merge($users,$result); + } + } + return $users; + } + + /** + * @brief check if a user exists + * @param string $uid the username + * @return boolean + */ + public static function userExists($uid){ + foreach(self::$_usedBackends as $backend){ + $result=$backend->userExists($uid); + if($result===true){ + return true; + } + } + return false; } }