From 2ceb4068adcf633c638d9d0c0b6e0f155b5aa86e Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 14 Aug 2019 18:13:39 +0200 Subject: [PATCH] =?UTF-8?q?N=C2=B02311=20-=20Refactor=20Login=20FSM=20Exte?= =?UTF-8?q?nsions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application/applicationextension.inc.php | 127 +++++++++++++++- application/loginbasic.class.inc.php | 135 ++++++++--------- application/logindefault.class.inc.php | 106 +++++++------ application/loginexternal.class.inc.php | 99 +++++-------- application/loginform.class.inc.php | 181 +++++++++++------------ application/loginurl.class.inc.php | 119 +++++++-------- application/loginwebpage.class.inc.php | 44 ++++-- core/metamodel.class.php | 2 +- pages/logoff.php | 31 ++-- 9 files changed, 472 insertions(+), 372 deletions(-) diff --git a/application/applicationextension.inc.php b/application/applicationextension.inc.php index db12a40aa..80e5e28cd 100644 --- a/application/applicationextension.inc.php +++ b/application/applicationextension.inc.php @@ -30,7 +30,7 @@ require_once(APPROOT.'application/newsroomprovider.class.inc.php'); * @api */ -interface iLoginFSMExtension +interface iLoginExtension { /** * Return the list of supported login modes for this plugin @@ -38,7 +38,10 @@ interface iLoginFSMExtension * @return array of supported login modes */ public function ListSupportedLoginModes(); +} +interface iLoginFSMExtension extends iLoginExtension +{ /** * Execute action for this login state * If a page is displayed, the action must exit at this point @@ -54,6 +57,128 @@ interface iLoginFSMExtension public function LoginAction($sLoginState, &$iErrorCode); } +abstract class AbstractLoginFSMExtension implements iLoginFSMExtension +{ + public abstract function ListSupportedLoginModes(); + + /** + * @inheritDoc + */ + public function LoginAction($sLoginState, &$iErrorCode) + { + switch ($sLoginState) + { + case LoginWebPage::LOGIN_STATE_START: + return $this->OnStart($iErrorCode); + + case LoginWebPage::LOGIN_STATE_MODE_DETECTION: + return $this->OnModeDetection($iErrorCode); + + case LoginWebPage::LOGIN_STATE_READ_CREDENTIALS: + return $this->OnReadCredentials($iErrorCode); + + case LoginWebPage::LOGIN_STATE_CHECK_CREDENTIALS: + return $this->OnCheckCredentials($iErrorCode); + + case LoginWebPage::LOGIN_STATE_CREDENTIALS_OK: + return $this->OnCredentialsOK($iErrorCode); + + case LoginWebPage::LOGIN_STATE_USER_OK: + return $this->OnUsersOK($iErrorCode); + + case LoginWebPage::LOGIN_STATE_CONNECTED: + return $this->OnConnected($iErrorCode); + + case LoginWebPage::LOGIN_STATE_ERROR: + return $this->OnError($iErrorCode); + } + + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + } + + /** + * Initialization + * + * @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...) + * + * @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_RETURN_IGNORE + */ + protected function OnStart(&$iErrorCode) + { + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + } + + /** + * Detect login mode explicitly without respecting configured order (legacy mode) + * In most case do nothing here + * + * @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...) + * + * @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_RETURN_IGNORE + */ + protected function OnModeDetection(&$iErrorCode) + { + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + } + + /** + * Obtain the credentials either if login mode is empty or set to yours. + * This step can be called multiple times by the FSM: + * for example: + * 1 - display login form + * 2 - read the values posted by the user + * + * @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...) + * + * @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_RETURN_IGNORE + */ + protected function OnReadCredentials(&$iErrorCode) + { + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + } + + /** + * Control the validity of the data provided by the user + * Automatic user provisioning can be done here + * + * @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...) + * + * @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_RETURN_IGNORE + */ + protected function OnCheckCredentials(&$iErrorCode) + { + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + } + + protected function OnCredentialsOK(&$iErrorCode) + { + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + } + + protected function OnUsersOK(&$iErrorCode) + { + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + } + + protected function OnConnected(&$iErrorCode) + { + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + } + + protected function OnError(&$iErrorCode) + { + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + } +} + +interface iLogoutExtension extends iLoginExtension +{ + /** + * Execute all actions to log out properly + */ + public function LogoutAction(); +} + /** * Implement this interface to change the behavior of the GUI for some objects. * diff --git a/application/loginbasic.class.inc.php b/application/loginbasic.class.inc.php index 056b140fe..3e8629b00 100644 --- a/application/loginbasic.class.inc.php +++ b/application/loginbasic.class.inc.php @@ -6,82 +6,8 @@ * @license http://opensource.org/licenses/AGPL-3.0 */ -class LoginBasic implements iLoginFSMExtension +class LoginBasic extends AbstractLoginFSMExtension { - /** - * Execute action for this login state - * If a page is displayed, the action must exit at this point - * - * @param string $sLoginState (see LoginWebPage::LOGIN_STATE_...) - * @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...) - * - * @return int LoginWebPage::LOGIN_FSM_RETURN_... - * - * @throws \ArchivedObjectException - * @throws \CoreCannotSaveObjectException - * @throws \CoreException - * @throws \CoreUnexpectedValue - * @throws \CoreWarning - * @throws \MySQLException - * @throws \OQLException - */ - public function LoginAction($sLoginState, &$iErrorCode) - { - switch ($sLoginState) - { - case LoginWebPage::LOGIN_STATE_MODE_DETECTION: - if (!isset($_SESSION['login_mode'])) - { - if (isset($_SERVER['HTTP_AUTHORIZATION']) && !empty($_SERVER['HTTP_AUTHORIZATION'])) - { - $_SESSION['login_mode'] = 'basic'; - } - elseif (isset($_SERVER['PHP_AUTH_USER'])) - { - $_SESSION['login_mode'] = 'basic'; - } - } - break; - - case LoginWebPage::LOGIN_STATE_CHECK_CREDENTIALS: - if ($_SESSION['login_mode'] == 'basic') - { - list($sAuthUser, $sAuthPwd) = $this->GetAuthUserAndPassword(); - if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, $_SESSION['login_mode'], 'internal')) - { - $iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS; - return LoginWebPage::LOGIN_FSM_RETURN_ERROR; - } - } - break; - - case LoginWebPage::LOGIN_STATE_CREDENTIAL_OK: - if ($_SESSION['login_mode'] == 'basic') - { - list($sAuthUser) = $this->GetAuthUserAndPassword(); - LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', $_SESSION['login_mode']); - } - break; - - case LoginWebPage::LOGIN_STATE_ERROR: - if ($_SESSION['login_mode'] == 'basic') - { - LoginWebPage::HTTP401Error(); - } - break; - - case LoginWebPage::LOGIN_STATE_CONNECTED: - if ($_SESSION['login_mode'] == 'basic') - { - $_SESSION['can_logoff'] = true; - return LoginWebPage::CheckLoggedUser($iErrorCode); - } - break; - } - - return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; - } - /** * Return the list of supported login modes for this plugin * @@ -92,6 +18,65 @@ class LoginBasic implements iLoginFSMExtension return array('basic'); } + protected function OnModeDetection(&$iErrorCode) + { + if (!isset($_SESSION['login_mode'])) + { + if (isset($_SERVER['HTTP_AUTHORIZATION']) && !empty($_SERVER['HTTP_AUTHORIZATION'])) + { + $_SESSION['login_mode'] = 'basic'; + } + elseif (isset($_SERVER['PHP_AUTH_USER'])) + { + $_SESSION['login_mode'] = 'basic'; + } + } + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + } + + protected function OnCheckCredentials(&$iErrorCode) + { + if ($_SESSION['login_mode'] == 'basic') + { + list($sAuthUser, $sAuthPwd) = $this->GetAuthUserAndPassword(); + if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, $_SESSION['login_mode'], 'internal')) + { + $iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS; + return LoginWebPage::LOGIN_FSM_RETURN_ERROR; + } + } + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + } + + protected function OnCredentialsOK(&$iErrorCode) + { + if ($_SESSION['login_mode'] == 'basic') + { + list($sAuthUser) = $this->GetAuthUserAndPassword(); + LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', $_SESSION['login_mode']); + } + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + } + + protected function OnError(&$iErrorCode) + { + if ($_SESSION['login_mode'] == 'basic') + { + LoginWebPage::HTTP401Error(); + } + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + } + + protected function OnConnected(&$iErrorCode) + { + if ($_SESSION['login_mode'] == 'basic') + { + $_SESSION['can_logoff'] = true; + return LoginWebPage::CheckLoggedUser($iErrorCode); + } + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + } + private function GetAuthUserAndPassword() { $sAuthUser = ''; diff --git a/application/logindefault.class.inc.php b/application/logindefault.class.inc.php index ebaf1a20e..6df6d5b0f 100644 --- a/application/logindefault.class.inc.php +++ b/application/logindefault.class.inc.php @@ -1,65 +1,81 @@ GetAllowedLoginTypes(); + $sProposedLoginMode = utils::ReadParam('login_mode', ''); + $index = array_search($sProposedLoginMode, $aAllowedLoginTypes); + if ($index !== false) + { + // Force login mode + $_SESSION['login_mode'] = $sProposedLoginMode; + } + else + { + unset($_SESSION['login_mode']); + } + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + } + + protected function OnError(&$iErrorCode) + { + $_SESSION['login_error_count'] = (isset($_SESSION['login_error_count']) ? $_SESSION['login_error_count'] : 0) + 1; + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + } + + protected function OnConnected(&$iErrorCode) + { + unset($_SESSION['login_error_count']); + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + } +} + +/** + * Class LoginDefaultAfter + */ +class LoginDefaultAfter extends AbstractLoginFSMExtension implements iLogoutExtension +{ + /** + * Must be executed after the other login plugins + * + * @return array of supported login modes + */ + public function ListSupportedLoginModes() + { + return array('after'); + } + + protected function OnError(&$iErrorCode) + { + unset($_SESSION['login_mode']); + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; } /** - * Execute action for this login state - * If a page is displayed, the action must exit at this point - * if LoginWebPage::LOGIN_FSM_RETURN_ERROR is returned $iErrorCode must be set - * if LoginWebPage::LOGIN_FSM_RETURN_OK is returned then the login is OK and terminated - * if LoginWebPage::LOGIN_FSM_RETURN_IGNORE is returned then the FSM will proceed to next plugin or state - * - * @param string $sLoginState (see LoginWebPage::LOGIN_STATE_...) - * @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...) - * - * @return int LoginWebPage::LOGIN_FSM_RETURN_ERROR, LoginWebPage::LOGIN_FSM_RETURN_OK or LoginWebPage::LOGIN_FSM_RETURN_IGNORE + * Execute all actions to log out properly */ - public function LoginAction($sLoginState, &$iErrorCode) + public function LogoutAction() { - switch ($sLoginState) - { - case LoginWebPage::LOGIN_STATE_START: - // Check if proposed login mode is present and allowed - $aAllowedLoginTypes = MetaModel::GetConfig()->GetAllowedLoginTypes(); - $sProposedLoginMode = utils::ReadParam('login_mode', ''); - $index = array_search($sProposedLoginMode, $aAllowedLoginTypes); - if ($index !== false) - { - // Force login mode - $_SESSION['login_mode'] = $sProposedLoginMode; - } - else - { - unset($_SESSION['login_mode']); - } - break; - - case LoginWebPage::LOGIN_STATE_ERROR: - $_SESSION['login_error_count'] = (isset($_SESSION['login_error_count']) ? $_SESSION['login_error_count'] : 0) + 1; - break; - - case LoginWebPage::LOGIN_STATE_CONNECTED: - unset($_SESSION['login_error_count']); - break; - } - - return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + unset($_SESSION['login_mode']); } } \ No newline at end of file diff --git a/application/loginexternal.class.inc.php b/application/loginexternal.class.inc.php index 65da5bf94..002f51616 100644 --- a/application/loginexternal.class.inc.php +++ b/application/loginexternal.class.inc.php @@ -7,7 +7,7 @@ * @license http://opensource.org/licenses/AGPL-3.0 */ -class LoginExternal implements iLoginFSMExtension +class LoginExternal extends AbstractLoginFSMExtension { /** @@ -20,67 +20,50 @@ class LoginExternal implements iLoginFSMExtension return array('external'); } - /** - * Execute action for this login state - * If a page is displayed, the action must exit at this point - * - * @param string $sLoginState (see LoginWebPage::LOGIN_STATE_...) - * @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...) - * - * @return int LoginWebPage::LOGIN_FSM_RETURN_... - * - * @throws \ArchivedObjectException - * @throws \CoreCannotSaveObjectException - * @throws \CoreException - * @throws \CoreUnexpectedValue - * @throws \CoreWarning - * @throws \MySQLException - * @throws \OQLException - */ - public function LoginAction($sLoginState, &$iErrorCode) + protected function OnModeDetection(&$iErrorCode) { - switch ($sLoginState) + if (!isset($_SESSION['login_mode'])) { - case LoginWebPage::LOGIN_STATE_MODE_DETECTION: - if (!isset($_SESSION['login_mode'])) - { - $sAuthUser = $this->GetAuthUser(); - if ($sAuthUser && (strlen($sAuthUser) > 0)) - { - $_SESSION['login_mode'] = 'external'; - } - } - break; - - case LoginWebPage::LOGIN_STATE_CHECK_CREDENTIALS: - if ($_SESSION['login_mode'] == 'external') - { - $sAuthUser = $this->GetAuthUser(); - if (!UserRights::CheckCredentials($sAuthUser, '', $_SESSION['login_mode'], 'external')) - { - $iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS; - return LoginWebPage::LOGIN_FSM_RETURN_ERROR; - } - } - break; - - case LoginWebPage::LOGIN_STATE_CREDENTIAL_OK: - if ($_SESSION['login_mode'] == 'external') - { - $sAuthUser = $this->GetAuthUser(); - LoginWebPage::OnLoginSuccess($sAuthUser, 'external', $_SESSION['login_mode']); - } - break; - - case LoginWebPage::LOGIN_STATE_CONNECTED: - if ($_SESSION['login_mode'] == 'external') - { - $_SESSION['can_logoff'] = false; - return LoginWebPage::CheckLoggedUser($iErrorCode); - } - break; + $sAuthUser = $this->GetAuthUser(); + if ($sAuthUser && (strlen($sAuthUser) > 0)) + { + $_SESSION['login_mode'] = 'external'; + } } + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + } + protected function OnCheckCredentials(&$iErrorCode) + { + if ($_SESSION['login_mode'] == 'external') + { + $sAuthUser = $this->GetAuthUser(); + if (!UserRights::CheckCredentials($sAuthUser, '', $_SESSION['login_mode'], 'external')) + { + $iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS; + return LoginWebPage::LOGIN_FSM_RETURN_ERROR; + } + } + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + } + + protected function OnCredentialsOK(&$iErrorCode) + { + if ($_SESSION['login_mode'] == 'external') + { + $sAuthUser = $this->GetAuthUser(); + LoginWebPage::OnLoginSuccess($sAuthUser, 'external', $_SESSION['login_mode']); + } + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + } + + protected function OnConnected(&$iErrorCode) + { + if ($_SESSION['login_mode'] == 'external') + { + $_SESSION['can_logoff'] = false; + return LoginWebPage::CheckLoggedUser($iErrorCode); + } return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; } diff --git a/application/loginform.class.inc.php b/application/loginform.class.inc.php index f81bde0bd..f66981618 100644 --- a/application/loginform.class.inc.php +++ b/application/loginform.class.inc.php @@ -7,106 +7,10 @@ * @license http://opensource.org/licenses/AGPL-3.0 */ -class LoginForm implements iLoginFSMExtension +class LoginForm extends AbstractLoginFSMExtension { private $bForceFormOnError = false; - /** - * Execute action for this login state - * If a page is displayed, the action must exit at this point - * - * @param string $sLoginState (see LoginWebPage::LOGIN_STATE_...) - * @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...) - * - * @return int LoginWebPage::LOGIN_FSM_RETURN_... - * - * @throws \ArchivedObjectException - * @throws \CoreCannotSaveObjectException - * @throws \CoreException - * @throws \CoreUnexpectedValue - * @throws \CoreWarning - * @throws \MySQLException - * @throws \OQLException - */ - public function LoginAction($sLoginState, &$iErrorCode) - { - switch ($sLoginState) - { - case LoginWebPage::LOGIN_STATE_MODE_DETECTION: - $sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data'); - $sAuthPwd = utils::ReadPostedParam('auth_pwd', null, 'raw_data'); - if (!empty($sAuthUser) && !empty($sAuthPwd)) - { - $_SESSION['login_mode'] = 'form'; - } - break; - - case LoginWebPage::LOGIN_STATE_READ_CREDENTIALS: - if (!isset($_SESSION['login_mode']) || ($_SESSION['login_mode'] == 'form')) - { - $sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data'); - $sAuthPwd = utils::ReadPostedParam('auth_pwd', null, 'raw_data'); - $_SESSION['login_mode'] = 'form'; - if ($this->bForceFormOnError || empty($sAuthUser) || empty($sAuthPwd)) - { - if (array_key_exists('HTTP_X_COMBODO_AJAX', $_SERVER)) - { - // X-Combodo-Ajax is a special header automatically added to all ajax requests - // Let's reply that we're currently logged-out - header('HTTP/1.0 401 Unauthorized'); - exit; - } - - // No credentials yet, display the form - $oPage = LoginWebPage::NewLoginWebPage(); - $oPage->DisplayLoginForm('form', $this->bForceFormOnError); - $oPage->output(); - $this->bForceFormOnError = false; - exit; - } - } - break; - - case LoginWebPage::LOGIN_STATE_CHECK_CREDENTIALS: - if ($_SESSION['login_mode'] == 'form') - { - $sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data'); - $sAuthPwd = utils::ReadPostedParam('auth_pwd', null, 'raw_data'); - if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, $_SESSION['login_mode'], 'internal')) - { - $iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS; - return LoginWebPage::LOGIN_FSM_RETURN_ERROR; - } - } - break; - - case LoginWebPage::LOGIN_STATE_CREDENTIAL_OK: - if ($_SESSION['login_mode'] == 'form') - { - $sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data'); - LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', $_SESSION['login_mode']); - } - break; - - case LoginWebPage::LOGIN_STATE_ERROR: - if ($_SESSION['login_mode'] == 'form') - { - $this->bForceFormOnError = true; - } - break; - - case LoginWebPage::LOGIN_STATE_CONNECTED: - if ($_SESSION['login_mode'] == 'form') - { - $_SESSION['can_logoff'] = true; - return LoginWebPage::CheckLoggedUser($iErrorCode); - } - break; - } - - return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; - } - /** * Return the list of supported login modes for this plugin * @@ -116,4 +20,87 @@ class LoginForm implements iLoginFSMExtension { return array('form'); } + + protected function OnModeDetection(&$iErrorCode) + { + $sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data'); + $sAuthPwd = utils::ReadPostedParam('auth_pwd', null, 'raw_data'); + if (!empty($sAuthUser) && !empty($sAuthPwd)) + { + $_SESSION['login_mode'] = 'form'; + } + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + } + + protected function OnReadCredentials(&$iErrorCode) + { + if (!isset($_SESSION['login_mode']) || ($_SESSION['login_mode'] == 'form')) + { + $sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data'); + $sAuthPwd = utils::ReadPostedParam('auth_pwd', null, 'raw_data'); + $_SESSION['login_mode'] = 'form'; + if ($this->bForceFormOnError || empty($sAuthUser) || empty($sAuthPwd)) + { + if (array_key_exists('HTTP_X_COMBODO_AJAX', $_SERVER)) + { + // X-Combodo-Ajax is a special header automatically added to all ajax requests + // Let's reply that we're currently logged-out + header('HTTP/1.0 401 Unauthorized'); + exit; + } + + // No credentials yet, display the form + $oPage = LoginWebPage::NewLoginWebPage(); + $oPage->DisplayLoginForm('form', $this->bForceFormOnError); + $oPage->output(); + $this->bForceFormOnError = false; + exit; + } + } + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + } + + protected function OnCheckCredentials(&$iErrorCode) + { + if ($_SESSION['login_mode'] == 'form') + { + $sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data'); + $sAuthPwd = utils::ReadPostedParam('auth_pwd', null, 'raw_data'); + if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, $_SESSION['login_mode'], 'internal')) + { + $iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS; + return LoginWebPage::LOGIN_FSM_RETURN_ERROR; + } + } + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + } + + protected function OnCredentialsOK(&$iErrorCode) + { + if ($_SESSION['login_mode'] == 'form') + { + $sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data'); + LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', $_SESSION['login_mode']); + } + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + } + + protected function OnError(&$iErrorCode) + { + if ($_SESSION['login_mode'] == 'form') + { + $this->bForceFormOnError = true; + } + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + } + + protected function OnConnected(&$iErrorCode) + { + if ($_SESSION['login_mode'] == 'form') + { + $_SESSION['can_logoff'] = true; + return LoginWebPage::CheckLoggedUser($iErrorCode); + } + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + } } diff --git a/application/loginurl.class.inc.php b/application/loginurl.class.inc.php index f513f4ecd..37d8c9e2c 100644 --- a/application/loginurl.class.inc.php +++ b/application/loginurl.class.inc.php @@ -7,7 +7,7 @@ * @license http://opensource.org/licenses/AGPL-3.0 */ -class LoginURL implements iLoginFSMExtension +class LoginURL extends AbstractLoginFSMExtension { /** * @var bool @@ -24,76 +24,61 @@ class LoginURL implements iLoginFSMExtension return array('url'); } - /** - * Execute action for this login state - * If a page is displayed, the action must exit at this point - * - * @param string $sLoginState (see LoginWebPage::LOGIN_STATE_...) - * @param int $iErrorCode (see LoginWebPage::EXIT_CODE_...) - * - * @return int LoginWebPage::LOGIN_FSM_RETURN_... - * - * @throws \ArchivedObjectException - * @throws \CoreCannotSaveObjectException - * @throws \CoreException - * @throws \CoreUnexpectedValue - * @throws \CoreWarning - * @throws \MySQLException - * @throws \OQLException - */ - public function LoginAction($sLoginState, &$iErrorCode) + protected function OnModeDetection(&$iErrorCode) { - switch ($sLoginState) + if (!isset($_SESSION['login_mode']) && !$this->bErrorOccurred) { - case LoginWebPage::LOGIN_STATE_MODE_DETECTION: - if (!isset($_SESSION['login_mode']) && !$this->bErrorOccurred) - { - $sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data'); - $sAuthPwd = utils::ReadParam('auth_pwd', null, false, 'raw_data'); - if (!empty($sAuthUser) && !empty($sAuthPwd)) - { - $_SESSION['login_mode'] = 'url'; - } - } - break; - - case LoginWebPage::LOGIN_STATE_CHECK_CREDENTIALS: - if ($_SESSION['login_mode'] == 'url') - { - $sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data'); - $sAuthPwd = utils::ReadParam('auth_pwd', null, false, 'raw_data'); - if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, $_SESSION['login_mode'], 'internal')) - { - $iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS; - return LoginWebPage::LOGIN_FSM_RETURN_ERROR; - } - } - break; - - case LoginWebPage::LOGIN_STATE_CREDENTIAL_OK: - if ($_SESSION['login_mode'] == 'url') - { - $sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data'); - LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', $_SESSION['login_mode']); - } - break; - - case LoginWebPage::LOGIN_STATE_ERROR: - if ($_SESSION['login_mode'] == 'url') - { - $this->bErrorOccurred = true; - } - break; - - case LoginWebPage::LOGIN_STATE_CONNECTED: - if ($_SESSION['login_mode'] == 'url') - { - $_SESSION['can_logoff'] = true; - return LoginWebPage::CheckLoggedUser($iErrorCode); - } - break; + $sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data'); + $sAuthPwd = utils::ReadParam('auth_pwd', null, false, 'raw_data'); + if (!empty($sAuthUser) && !empty($sAuthPwd)) + { + $_SESSION['login_mode'] = 'url'; + } } + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + } + protected function OnCheckCredentials(&$iErrorCode) + { + if ($_SESSION['login_mode'] == 'url') + { + $sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data'); + $sAuthPwd = utils::ReadParam('auth_pwd', null, false, 'raw_data'); + if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, $_SESSION['login_mode'], 'internal')) + { + $iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS; + return LoginWebPage::LOGIN_FSM_RETURN_ERROR; + } + } + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + } + + protected function OnCredentialsOK(&$iErrorCode) + { + if ($_SESSION['login_mode'] == 'url') + { + $sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data'); + LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', $_SESSION['login_mode']); + } + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + } + + protected function OnError(&$iErrorCode) + { + if ($_SESSION['login_mode'] == 'url') + { + $this->bErrorOccurred = true; + } + return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; + } + + protected function OnConnected(&$iErrorCode) + { + if ($_SESSION['login_mode'] == 'url') + { + $_SESSION['can_logoff'] = true; + return LoginWebPage::CheckLoggedUser($iErrorCode); + } return LoginWebPage::LOGIN_FSM_RETURN_CONTINUE; } } \ No newline at end of file diff --git a/application/loginwebpage.class.inc.php b/application/loginwebpage.class.inc.php index b0d5403bd..1ee222aca 100644 --- a/application/loginwebpage.class.inc.php +++ b/application/loginwebpage.class.inc.php @@ -49,7 +49,7 @@ class LoginWebPage extends NiceWebPage const LOGIN_STATE_MODE_DETECTION = 'login mode detection'; // Detect which login plugin to use const LOGIN_STATE_READ_CREDENTIALS = 'read credentials'; // Read the credentials const LOGIN_STATE_CHECK_CREDENTIALS = 'check credentials'; // Check if the credentials are valid - const LOGIN_STATE_CREDENTIAL_OK = 'credentials ok'; // User provisioning + const LOGIN_STATE_CREDENTIALS_OK = 'credentials ok'; // User provisioning const LOGIN_STATE_USER_OK = 'user ok'; // Additional check (2FA) const LOGIN_STATE_CONNECTED = 'connected'; // User connected const LOGIN_STATE_SET_ERROR = 'prepare for error'; // Internal state to trigger ERROR state @@ -453,6 +453,28 @@ EOF $this->add("\n"); } + public function DisplayLogoutPage($bPortal) + { + $sUrl = utils::GetAbsoluteUrlAppRoot(); + if ($bPortal) + { + $sUrl .= 'portal/'; + } + else + { + $sUrl .= 'pages/UI.php'; + } + + $this->no_cache(); + $this->DisplayLoginHeader(); + $this->add("
\n"); + $this->add("

".Dict::S('UI:LogOff:ThankYou')."

\n"); + + $this->add("

".Dict::S('UI:LogOff:ClickHereToLoginAgain')."

"); + $this->add("
\n"); + $this->output(); + } + static function ResetSession() { // Unset all of the session variables. @@ -584,34 +606,36 @@ EOF * Get plugins list ordered by config 'allowed_login_types' * Use the login mode to filter plugins * + * @param string $sInterface 'iLoginFSMExtension' or 'iLogoutExtension' + * * @return array of plugins */ - private static function GetLoginPluginList() + public static function GetLoginPluginList($sInterface = 'iLoginFSMExtension') { $aAllPlugins = array(); // Keep only the plugins for the current login mode $sCurrentLoginMode = isset($_SESSION['login_mode']) ? $_SESSION['login_mode'] : ''; - /** @var iLoginFSMExtension $oLoginFSMExtensionInstance */ - foreach (MetaModel::EnumPlugins('iLoginFSMExtension') as $oLoginFSMExtensionInstance) + /** @var iLoginExtension $oLoginExtensionInstance */ + foreach (MetaModel::EnumPlugins($sInterface) as $oLoginExtensionInstance) { - $aLoginModes = $oLoginFSMExtensionInstance->ListSupportedLoginModes(); + $aLoginModes = $oLoginExtensionInstance->ListSupportedLoginModes(); foreach ($aLoginModes as $sLoginMode) { - if (empty($sCurrentLoginMode) || ($sLoginMode == 'default') || ($sLoginMode == $sCurrentLoginMode)) + if (empty($sCurrentLoginMode) || ($sLoginMode == 'before') || ($sLoginMode == 'after') || ($sLoginMode == $sCurrentLoginMode)) { if (!isset($aAllPlugins[$sLoginMode])) { $aAllPlugins[$sLoginMode] = array(); } - $aAllPlugins[$sLoginMode][] = $oLoginFSMExtensionInstance; + $aAllPlugins[$sLoginMode][] = $oLoginExtensionInstance; } } } // Order by the config list of allowed types - $aAllowedLoginModes = array_merge(array('default'), MetaModel::GetConfig()->GetAllowedLoginTypes()); + $aAllowedLoginModes = array_merge(array('before'), MetaModel::GetConfig()->GetAllowedLoginTypes(), array('after')); $aPlugins = array(); foreach ($aAllowedLoginModes as $sAllowedMode) { @@ -644,9 +668,9 @@ EOF return self::LOGIN_STATE_CHECK_CREDENTIALS; case self::LOGIN_STATE_CHECK_CREDENTIALS: - return self::LOGIN_STATE_CREDENTIAL_OK; + return self::LOGIN_STATE_CREDENTIALS_OK; - case self::LOGIN_STATE_CREDENTIAL_OK: + case self::LOGIN_STATE_CREDENTIALS_OK: return self::LOGIN_STATE_USER_OK; case self::LOGIN_STATE_USER_OK: diff --git a/core/metamodel.class.php b/core/metamodel.class.php index 07d17252b..6769f2b44 100644 --- a/core/metamodel.class.php +++ b/core/metamodel.class.php @@ -2780,7 +2780,7 @@ abstract class MetaModel // Build the list of available extensions // - $aInterfaces = array('iApplicationUIExtension', 'iApplicationObjectExtension', 'iLoginFSMExtension', 'iQueryModifier', 'iOnClassInitialization', 'iPopupMenuExtension', 'iPageUIExtension', 'iPortalUIExtension', 'ModuleHandlerApiInterface', 'iNewsroomProvider'); + $aInterfaces = array('iApplicationUIExtension', 'iApplicationObjectExtension', 'iLoginFSMExtension', 'iLogoutExtension', 'iQueryModifier', 'iOnClassInitialization', 'iPopupMenuExtension', 'iPageUIExtension', 'iPortalUIExtension', 'ModuleHandlerApiInterface', 'iNewsroomProvider'); foreach($aInterfaces as $sInterface) { self::$m_aExtensionClasses[$sInterface] = array(); diff --git a/pages/logoff.php b/pages/logoff.php index f4fd08c8e..ee26f71bd 100644 --- a/pages/logoff.php +++ b/pages/logoff.php @@ -43,22 +43,23 @@ if ($operation == 'do_logoff') exit; } -if ($bPortal) -{ - $sUrl .= 'portal/'; -} -else -{ - $sUrl .= 'pages/UI.php'; -} if (isset($_SESSION['auth_user'])) { $sAuthUser = $_SESSION['auth_user']; UserRights::Login($sAuthUser); // Set the user's language } -$sLoginMode = isset($_SESSION['login_mode']) ? $_SESSION['login_mode'] : ''; LoginWebPage::ResetSession(); + +$aPluginList = LoginWebPage::GetLoginPluginList('iLogoutExtension'); + +/** @var iLogoutExtension $oLogoutExtension */ +foreach ($aPluginList as $oLogoutExtension) +{ + $oLogoutExtension->LogoutAction(); +} + +/* switch($sLoginMode) { case 'cas': @@ -71,13 +72,7 @@ switch($sLoginMode) phpCAS::logoutWithRedirectService($sCASLogoutUrl); // Redirects to the CAS logout page break; } -$oPage = LoginWebPage::NewLoginWebPage(); -$oPage->no_cache(); -$oPage->DisplayLoginHeader(); -$oPage->add("
\n"); -$oPage->add("

".Dict::S('UI:LogOff:ThankYou')."

\n"); +*/ -$oPage->add("

".Dict::S('UI:LogOff:ClickHereToLoginAgain')."

"); -$oPage->add("
\n"); -$oPage->output(); -?> +$oPage = LoginWebPage::NewLoginWebPage(); +$oPage->DisplayLogoutPage($bPortal);