From: Craig Andrews Date: Tue, 5 Jan 2010 18:56:22 +0000 (-0500) Subject: Move Authorization and Authentication plugin structures into core, instead of as... X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=9e2e0605ed6280daa4d74c4b962e4630d1078d90;p=quix0rs-gnu-social.git Move Authorization and Authentication plugin structures into core, instead of as plugins. This move makes sense as you can addPlugin('Authentication') for example - these are abstract classes designed to be implemented, not used directly. --- diff --git a/classes/User_username.php b/classes/User_username.php new file mode 100644 index 0000000000..853fd5cb86 --- /dev/null +++ b/classes/User_username.php @@ -0,0 +1,61 @@ +user_id = $user->id; + $user_username->provider_name = $provider_name; + $user_username->username = $username; + $user_username->created = DB_DataObject_Cast::dateTime(); + if($user_username->insert()){ + return $user_username; + }else{ + return false; + } + } + + function table() { + return array( + 'user_id' => DB_DATAOBJECT_INT, + 'username' => DB_DATAOBJECT_STR, + 'provider_name' => DB_DATAOBJECT_STR , + 'created' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME + ); + } + + // now define the keys. + function keys() { + return array('provider_name', 'username'); + } + +} diff --git a/lib/authenticationplugin.php b/lib/authenticationplugin.php new file mode 100644 index 0000000000..de479a5768 --- /dev/null +++ b/lib/authenticationplugin.php @@ -0,0 +1,231 @@ +. + * + * @category Plugin + * @package StatusNet + * @author Craig Andrews + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET') && !defined('LACONICA')) { + exit(1); +} + +/** + * Superclass for plugins that do authentication + * + * @category Plugin + * @package StatusNet + * @author Craig Andrews + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +abstract class AuthenticationPlugin extends Plugin +{ + //is this plugin authoritative for authentication? + public $authoritative = false; + + //should accounts be automatically created after a successful login attempt? + public $autoregistration = false; + + //can the user change their email address + public $password_changeable=true; + + //unique name for this authentication provider + public $provider_name; + + //------------Auth plugin should implement some (or all) of these methods------------\\ + /** + * Check if a nickname/password combination is valid + * @param username + * @param password + * @return boolean true if the credentials are valid, false if they are invalid. + */ + function checkPassword($username, $password) + { + return false; + } + + /** + * Automatically register a user when they attempt to login with valid credentials. + * User::register($data) is a very useful method for this implementation + * @param username + * @return mixed instance of User, or false (if user couldn't be created) + */ + function autoRegister($username) + { + $registration_data = array(); + $registration_data['nickname'] = $username ; + return User::register($registration_data); + } + + /** + * Change a user's password + * The old password has been verified to be valid by this plugin before this call is made + * @param username + * @param oldpassword + * @param newpassword + * @return boolean true if the password was changed, false if password changing failed for some reason + */ + function changePassword($username,$oldpassword,$newpassword) + { + return false; + } + + //------------Below are the methods that connect StatusNet to the implementing Auth plugin------------\\ + function onInitializePlugin(){ + if(!isset($this->provider_name)){ + throw new Exception("must specify a provider_name for this authentication provider"); + } + } + + /** + * Internal AutoRegister event handler + * @param nickname + * @param provider_name + * @param user - the newly registered user + */ + function onAutoRegister($nickname, $provider_name, &$user) + { + if($provider_name == $this->provider_name && $this->autoregistration){ + $user = $this->autoregister($nickname); + if($user){ + User_username::register($user,$nickname,$this->provider_name); + return false; + } + } + } + + function onStartCheckPassword($nickname, $password, &$authenticatedUser){ + //map the nickname to a username + $user_username = new User_username(); + $user_username->username=$nickname; + $user_username->provider_name=$this->provider_name; + if($user_username->find() && $user_username->fetch()){ + $username = $user_username->username; + $authenticated = $this->checkPassword($username, $password); + if($authenticated){ + $authenticatedUser = User::staticGet('id', $user_username->user_id); + return false; + } + }else{ + $user = User::staticGet('nickname', $nickname); + if($user){ + //make sure a different provider isn't handling this nickname + $user_username = new User_username(); + $user_username->username=$nickname; + if(!$user_username->find()){ + //no other provider claims this username, so it's safe for us to handle it + $authenticated = $this->checkPassword($nickname, $password); + if($authenticated){ + $authenticatedUser = User::staticGet('nickname', $nickname); + User_username::register($authenticatedUser,$nickname,$this->provider_name); + return false; + } + } + }else{ + $authenticated = $this->checkPassword($nickname, $password); + if($authenticated){ + if(! Event::handle('AutoRegister', array($nickname, $this->provider_name, &$authenticatedUser))){ + //unlike most Event::handle lines of code, this one has a ! (not) + //we want to do this if the event *was* handled - this isn't a "default" implementation + //like most code of this form. + if($authenticatedUser){ + return false; + } + } + } + } + } + if($this->authoritative){ + return false; + }else{ + //we're not authoritative, so let other handlers try + return; + } + } + + function onStartChangePassword($user,$oldpassword,$newpassword) + { + if($this->password_changeable){ + $user_username = new User_username(); + $user_username->user_id=$user->id; + $user_username->provider_name=$this->provider_name; + if($user_username->find() && $user_username->fetch()){ + $authenticated = $this->checkPassword($user_username->username, $oldpassword); + if($authenticated){ + $result = $this->changePassword($user_username->username,$oldpassword,$newpassword); + if($result){ + //stop handling of other handlers, because what was requested was done + return false; + }else{ + throw new Exception(_('Password changing failed')); + } + }else{ + if($this->authoritative){ + //since we're authoritative, no other plugin could do this + throw new Exception(_('Password changing failed')); + }else{ + //let another handler try + return null; + } + } + } + }else{ + if($this->authoritative){ + //since we're authoritative, no other plugin could do this + throw new Exception(_('Password changing is not allowed')); + } + } + } + + function onStartAccountSettingsPasswordMenuItem($widget) + { + if($this->authoritative && !$this->password_changeable){ + //since we're authoritative, no other plugin could change passwords, so do not render the menu item + return false; + } + } + + function onCheckSchema() { + $schema = Schema::get(); + $schema->ensureTable('user_username', + array(new ColumnDef('provider_name', 'varchar', + '255', false, 'PRI'), + new ColumnDef('username', 'varchar', + '255', false, 'PRI'), + new ColumnDef('user_id', 'integer', + null, false), + new ColumnDef('created', 'datetime', + null, false), + new ColumnDef('modified', 'timestamp'))); + return true; + } + + function onUserDeleteRelated($user, &$tables) + { + $tables[] = 'User_username'; + return true; + } +} + diff --git a/lib/authorizationplugin.php b/lib/authorizationplugin.php new file mode 100644 index 0000000000..733b0c0656 --- /dev/null +++ b/lib/authorizationplugin.php @@ -0,0 +1,105 @@ +. + * + * @category Plugin + * @package StatusNet + * @author Craig Andrews + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET') && !defined('LACONICA')) { + exit(1); +} + +/** + * Superclass for plugins that do authorization + * + * @category Plugin + * @package StatusNet + * @author Craig Andrews + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +abstract class AuthorizationPlugin extends Plugin +{ + //is this plugin authoritative for authorization? + public $authoritative = false; + + //------------Auth plugin should implement some (or all) of these methods------------\\ + + /** + * Is a user allowed to log in? + * @param user + * @return boolean true if the user is allowed to login, false if explicitly not allowed to login, null if we don't explicitly allow or deny login + */ + function loginAllowed($user) { + return null; + } + + /** + * Does a profile grant the user a named role? + * @param profile + * @return boolean true if the profile has the role, false if not + */ + function hasRole($profile, $name) { + return false; + } + + //------------Below are the methods that connect StatusNet to the implementing Auth plugin------------\\ + + function onStartSetUser(&$user) { + $loginAllowed = $this->loginAllowed($user); + if($loginAllowed === true){ + return; + }else if($loginAllowed === false){ + $user = null; + return false; + }else{ + if($this->authoritative) { + $user = null; + return false; + }else{ + return; + } + } + } + + function onStartSetApiUser(&$user) { + return $this->onStartSetUser(&$user); + } + + function onStartHasRole($profile, $name, &$has_role) { + if($this->hasRole($profile, $name)){ + $has_role = true; + return false; + }else{ + if($this->authoritative) { + $has_role = false; + return false; + }else{ + return; + } + } + } +} + diff --git a/plugins/Authentication/AuthenticationPlugin.php b/plugins/Authentication/AuthenticationPlugin.php deleted file mode 100644 index 07f14035da..0000000000 --- a/plugins/Authentication/AuthenticationPlugin.php +++ /dev/null @@ -1,243 +0,0 @@ -. - * - * @category Plugin - * @package StatusNet - * @author Craig Andrews - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://status.net/ - */ - -if (!defined('STATUSNET') && !defined('LACONICA')) { - exit(1); -} - -/** - * Superclass for plugins that do authentication - * - * @category Plugin - * @package StatusNet - * @author Craig Andrews - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://status.net/ - */ - -abstract class AuthenticationPlugin extends Plugin -{ - //is this plugin authoritative for authentication? - public $authoritative = false; - - //should accounts be automatically created after a successful login attempt? - public $autoregistration = false; - - //can the user change their email address - public $password_changeable=true; - - //unique name for this authentication provider - public $provider_name; - - //------------Auth plugin should implement some (or all) of these methods------------\\ - /** - * Check if a nickname/password combination is valid - * @param username - * @param password - * @return boolean true if the credentials are valid, false if they are invalid. - */ - function checkPassword($username, $password) - { - return false; - } - - /** - * Automatically register a user when they attempt to login with valid credentials. - * User::register($data) is a very useful method for this implementation - * @param username - * @return mixed instance of User, or false (if user couldn't be created) - */ - function autoRegister($username) - { - $registration_data = array(); - $registration_data['nickname'] = $username ; - return User::register($registration_data); - } - - /** - * Change a user's password - * The old password has been verified to be valid by this plugin before this call is made - * @param username - * @param oldpassword - * @param newpassword - * @return boolean true if the password was changed, false if password changing failed for some reason - */ - function changePassword($username,$oldpassword,$newpassword) - { - return false; - } - - //------------Below are the methods that connect StatusNet to the implementing Auth plugin------------\\ - function onInitializePlugin(){ - if(!isset($this->provider_name)){ - throw new Exception("must specify a provider_name for this authentication provider"); - } - } - - /** - * Internal AutoRegister event handler - * @param nickname - * @param provider_name - * @param user - the newly registered user - */ - function onAutoRegister($nickname, $provider_name, &$user) - { - if($provider_name == $this->provider_name && $this->autoregistration){ - $user = $this->autoregister($nickname); - if($user){ - User_username::register($user,$nickname,$this->provider_name); - return false; - } - } - } - - function onStartCheckPassword($nickname, $password, &$authenticatedUser){ - //map the nickname to a username - $user_username = new User_username(); - $user_username->username=$nickname; - $user_username->provider_name=$this->provider_name; - if($user_username->find() && $user_username->fetch()){ - $username = $user_username->username; - $authenticated = $this->checkPassword($username, $password); - if($authenticated){ - $authenticatedUser = User::staticGet('id', $user_username->user_id); - return false; - } - }else{ - $user = User::staticGet('nickname', $nickname); - if($user){ - //make sure a different provider isn't handling this nickname - $user_username = new User_username(); - $user_username->username=$nickname; - if(!$user_username->find()){ - //no other provider claims this username, so it's safe for us to handle it - $authenticated = $this->checkPassword($nickname, $password); - if($authenticated){ - $authenticatedUser = User::staticGet('nickname', $nickname); - User_username::register($authenticatedUser,$nickname,$this->provider_name); - return false; - } - } - }else{ - $authenticated = $this->checkPassword($nickname, $password); - if($authenticated){ - if(! Event::handle('AutoRegister', array($nickname, $this->provider_name, &$authenticatedUser))){ - //unlike most Event::handle lines of code, this one has a ! (not) - //we want to do this if the event *was* handled - this isn't a "default" implementation - //like most code of this form. - if($authenticatedUser){ - return false; - } - } - } - } - } - if($this->authoritative){ - return false; - }else{ - //we're not authoritative, so let other handlers try - return; - } - } - - function onStartChangePassword($user,$oldpassword,$newpassword) - { - if($this->password_changeable){ - $user_username = new User_username(); - $user_username->user_id=$user->id; - $user_username->provider_name=$this->provider_name; - if($user_username->find() && $user_username->fetch()){ - $authenticated = $this->checkPassword($user_username->username, $oldpassword); - if($authenticated){ - $result = $this->changePassword($user_username->username,$oldpassword,$newpassword); - if($result){ - //stop handling of other handlers, because what was requested was done - return false; - }else{ - throw new Exception(_('Password changing failed')); - } - }else{ - if($this->authoritative){ - //since we're authoritative, no other plugin could do this - throw new Exception(_('Password changing failed')); - }else{ - //let another handler try - return null; - } - } - } - }else{ - if($this->authoritative){ - //since we're authoritative, no other plugin could do this - throw new Exception(_('Password changing is not allowed')); - } - } - } - - function onStartAccountSettingsPasswordMenuItem($widget) - { - if($this->authoritative && !$this->password_changeable){ - //since we're authoritative, no other plugin could change passwords, so do not render the menu item - return false; - } - } - - function onAutoload($cls) - { - switch ($cls) - { - case 'User_username': - require_once(INSTALLDIR.'/plugins/Authentication/User_username.php'); - return false; - default: - return true; - } - } - - function onCheckSchema() { - $schema = Schema::get(); - $schema->ensureTable('user_username', - array(new ColumnDef('provider_name', 'varchar', - '255', false, 'PRI'), - new ColumnDef('username', 'varchar', - '255', false, 'PRI'), - new ColumnDef('user_id', 'integer', - null, false), - new ColumnDef('created', 'datetime', - null, false), - new ColumnDef('modified', 'timestamp'))); - return true; - } - - function onUserDeleteRelated($user, &$tables) - { - $tables[] = 'User_username'; - return true; - } -} - diff --git a/plugins/Authentication/User_username.php b/plugins/Authentication/User_username.php deleted file mode 100644 index 853fd5cb86..0000000000 --- a/plugins/Authentication/User_username.php +++ /dev/null @@ -1,61 +0,0 @@ -user_id = $user->id; - $user_username->provider_name = $provider_name; - $user_username->username = $username; - $user_username->created = DB_DataObject_Cast::dateTime(); - if($user_username->insert()){ - return $user_username; - }else{ - return false; - } - } - - function table() { - return array( - 'user_id' => DB_DATAOBJECT_INT, - 'username' => DB_DATAOBJECT_STR, - 'provider_name' => DB_DATAOBJECT_STR , - 'created' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME - ); - } - - // now define the keys. - function keys() { - return array('provider_name', 'username'); - } - -} diff --git a/plugins/Authorization/AuthorizationPlugin.php b/plugins/Authorization/AuthorizationPlugin.php deleted file mode 100644 index e4e046d088..0000000000 --- a/plugins/Authorization/AuthorizationPlugin.php +++ /dev/null @@ -1,108 +0,0 @@ -. - * - * @category Plugin - * @package StatusNet - * @author Craig Andrews - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://status.net/ - */ - -if (!defined('STATUSNET') && !defined('LACONICA')) { - exit(1); -} - -/** - * Superclass for plugins that do authorization - * - * @category Plugin - * @package StatusNet - * @author Craig Andrews - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://status.net/ - */ - -abstract class AuthorizationPlugin extends Plugin -{ - //is this plugin authoritative for authorization? - public $authoritative = false; - - //------------Auth plugin should implement some (or all) of these methods------------\\ - - /** - * Is a user allowed to log in? - * @param user - * @return boolean true if the user is allowed to login, false if explicitly not allowed to login, null if we don't explicitly allow or deny login - */ - function loginAllowed($user) { - return null; - } - - /** - * Does a profile grant the user a named role? - * @param profile - * @return boolean true if the profile has the role, false if not - */ - function hasRole($profile, $name) { - return false; - } - - //------------Below are the methods that connect StatusNet to the implementing Auth plugin------------\\ - function onInitializePlugin(){ - - } - - function onStartSetUser(&$user) { - $loginAllowed = $this->loginAllowed($user); - if($loginAllowed === true){ - return; - }else if($loginAllowed === false){ - $user = null; - return false; - }else{ - if($this->authoritative) { - $user = null; - return false; - }else{ - return; - } - } - } - - function onStartSetApiUser(&$user) { - return $this->onStartSetUser(&$user); - } - - function onStartHasRole($profile, $name, &$has_role) { - if($this->hasRole($profile, $name)){ - $has_role = true; - return false; - }else{ - if($this->authoritative) { - $has_role = false; - return false; - }else{ - return; - } - } - } -} - diff --git a/plugins/CasAuthentication/CasAuthenticationPlugin.php b/plugins/CasAuthentication/CasAuthenticationPlugin.php index 8f29c7d2ad..26f21af160 100644 --- a/plugins/CasAuthentication/CasAuthenticationPlugin.php +++ b/plugins/CasAuthentication/CasAuthenticationPlugin.php @@ -34,7 +34,6 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { // We bundle the phpCAS library... set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . '/extlib/CAS'); -require_once INSTALLDIR.'/plugins/Authentication/AuthenticationPlugin.php'; class CasAuthenticationPlugin extends AuthenticationPlugin { public $server; diff --git a/plugins/LdapAuthentication/LdapAuthenticationPlugin.php b/plugins/LdapAuthentication/LdapAuthenticationPlugin.php index 39967fe425..af42be761e 100644 --- a/plugins/LdapAuthentication/LdapAuthenticationPlugin.php +++ b/plugins/LdapAuthentication/LdapAuthenticationPlugin.php @@ -31,7 +31,6 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } -require_once INSTALLDIR.'/plugins/Authentication/AuthenticationPlugin.php'; require_once 'Net/LDAP2.php'; class LdapAuthenticationPlugin extends AuthenticationPlugin diff --git a/plugins/LdapAuthorization/LdapAuthorizationPlugin.php b/plugins/LdapAuthorization/LdapAuthorizationPlugin.php index 5e759c3793..7673e61efb 100644 --- a/plugins/LdapAuthorization/LdapAuthorizationPlugin.php +++ b/plugins/LdapAuthorization/LdapAuthorizationPlugin.php @@ -31,7 +31,6 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } -require_once INSTALLDIR.'/plugins/Authorization/AuthorizationPlugin.php'; require_once 'Net/LDAP2.php'; class LdapAuthorizationPlugin extends AuthorizationPlugin diff --git a/plugins/ReverseUsernameAuthentication/ReverseUsernameAuthenticationPlugin.php b/plugins/ReverseUsernameAuthentication/ReverseUsernameAuthenticationPlugin.php index d48283b2ee..d157ea067c 100644 --- a/plugins/ReverseUsernameAuthentication/ReverseUsernameAuthenticationPlugin.php +++ b/plugins/ReverseUsernameAuthentication/ReverseUsernameAuthenticationPlugin.php @@ -31,8 +31,6 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } -require_once INSTALLDIR.'/plugins/Authentication/AuthenticationPlugin.php'; - class ReverseUsernameAuthenticationPlugin extends AuthenticationPlugin { //---interface implementation---//