From ae4b03163792f0b6e933933e5d37df87dc3fd566 Mon Sep 17 00:00:00 2001 From: mattab Date: Thu, 28 Mar 2013 12:42:39 +1300 Subject: Mass conversion of all files to the newly agreed coding standard: PSR 1/2 Converting Piwik core source files, PHP, JS, TPL, CSS More info: http://piwik.org/participate/coding-standards/ --- plugins/Login/Auth.php | 177 ++++--- plugins/Login/Controller.php | 972 +++++++++++++++++------------------- plugins/Login/FormLogin.php | 36 +- plugins/Login/FormResetPassword.php | 32 +- plugins/Login/Login.php | 355 +++++++------ plugins/Login/templates/header.tpl | 114 +++-- plugins/Login/templates/login.css | 251 +++++----- plugins/Login/templates/login.js | 191 ++++--- plugins/Login/templates/login.tpl | 141 +++--- plugins/Login/templates/message.tpl | 14 +- 10 files changed, 1118 insertions(+), 1165 deletions(-) (limited to 'plugins/Login') diff --git a/plugins/Login/Auth.php b/plugins/Login/Auth.php index c8c58e7aaf..a7a8a2e490 100644 --- a/plugins/Login/Auth.php +++ b/plugins/Login/Auth.php @@ -15,106 +15,101 @@ */ class Piwik_Login_Auth implements Piwik_Auth { - protected $login = null; - protected $token_auth = null; + protected $login = null; + protected $token_auth = null; - /** - * Authentication module's name, e.g., "Login" - * - * @return string - */ - public function getName() - { - return 'Login'; - } + /** + * Authentication module's name, e.g., "Login" + * + * @return string + */ + public function getName() + { + return 'Login'; + } - /** - * Authenticates user - * - * @return Piwik_Auth_Result - */ - public function authenticate() - { - $rootLogin = Piwik_Config::getInstance()->superuser['login']; - $rootPassword = Piwik_Config::getInstance()->superuser['password']; - $rootToken = Piwik_UsersManager_API::getInstance()->getTokenAuth($rootLogin, $rootPassword); + /** + * Authenticates user + * + * @return Piwik_Auth_Result + */ + public function authenticate() + { + $rootLogin = Piwik_Config::getInstance()->superuser['login']; + $rootPassword = Piwik_Config::getInstance()->superuser['password']; + $rootToken = Piwik_UsersManager_API::getInstance()->getTokenAuth($rootLogin, $rootPassword); - if(is_null($this->login)) - { - if($this->token_auth === $rootToken) - { - return new Piwik_Auth_Result(Piwik_Auth_Result::SUCCESS_SUPERUSER_AUTH_CODE, $rootLogin, $this->token_auth ); - } + if (is_null($this->login)) { + if ($this->token_auth === $rootToken) { + return new Piwik_Auth_Result(Piwik_Auth_Result::SUCCESS_SUPERUSER_AUTH_CODE, $rootLogin, $this->token_auth); + } - $login = Piwik_FetchOne( - 'SELECT login - FROM '.Piwik_Common::prefixTable('user').' + $login = Piwik_FetchOne( + 'SELECT login + FROM ' . Piwik_Common::prefixTable('user') . ' WHERE token_auth = ?', - array($this->token_auth) - ); - if(!empty($login)) - { - return new Piwik_Auth_Result(Piwik_Auth_Result::SUCCESS, $login, $this->token_auth ); - } - } - else if(!empty($this->login)) - { - if($this->login === $rootLogin - && ($this->getHashTokenAuth($rootLogin, $rootToken) === $this->token_auth) - || $rootToken === $this->token_auth) - { - $this->setTokenAuth($rootToken); - return new Piwik_Auth_Result(Piwik_Auth_Result::SUCCESS_SUPERUSER_AUTH_CODE, $rootLogin, $this->token_auth ); - } + array($this->token_auth) + ); + if (!empty($login)) { + return new Piwik_Auth_Result(Piwik_Auth_Result::SUCCESS, $login, $this->token_auth); + } + } else if (!empty($this->login)) { + if ($this->login === $rootLogin + && ($this->getHashTokenAuth($rootLogin, $rootToken) === $this->token_auth) + || $rootToken === $this->token_auth + ) { + $this->setTokenAuth($rootToken); + return new Piwik_Auth_Result(Piwik_Auth_Result::SUCCESS_SUPERUSER_AUTH_CODE, $rootLogin, $this->token_auth); + } - $login = $this->login; - $userToken = Piwik_FetchOne( - 'SELECT token_auth - FROM '.Piwik_Common::prefixTable('user').' + $login = $this->login; + $userToken = Piwik_FetchOne( + 'SELECT token_auth + FROM ' . Piwik_Common::prefixTable('user') . ' WHERE login = ?', - array($login) - ); - if(!empty($userToken) - && (($this->getHashTokenAuth($login, $userToken) === $this->token_auth) - || $userToken === $this->token_auth)) - { - $this->setTokenAuth($userToken); - return new Piwik_Auth_Result(Piwik_Auth_Result::SUCCESS, $login, $userToken ); - } - } + array($login) + ); + if (!empty($userToken) + && (($this->getHashTokenAuth($login, $userToken) === $this->token_auth) + || $userToken === $this->token_auth) + ) { + $this->setTokenAuth($userToken); + return new Piwik_Auth_Result(Piwik_Auth_Result::SUCCESS, $login, $userToken); + } + } - return new Piwik_Auth_Result( Piwik_Auth_Result::FAILURE, $this->login, $this->token_auth ); - } + return new Piwik_Auth_Result(Piwik_Auth_Result::FAILURE, $this->login, $this->token_auth); + } - /** - * Accessor to set login name - * - * @param string $login user login - */ - public function setLogin($login) - { - $this->login = $login; - } + /** + * Accessor to set login name + * + * @param string $login user login + */ + public function setLogin($login) + { + $this->login = $login; + } - /** - * Accessor to set authentication token - * - * @param string $token_auth authentication token - */ - public function setTokenAuth($token_auth) - { - $this->token_auth = $token_auth; - } + /** + * Accessor to set authentication token + * + * @param string $token_auth authentication token + */ + public function setTokenAuth($token_auth) + { + $this->token_auth = $token_auth; + } - /** - * Accessor to compute the hashed authentication token - * - * @param string $login user login - * @param string $token_auth authentication token - * @return string hashed authentication token - */ - public function getHashTokenAuth($login, $token_auth) - { - return md5($login . $token_auth); - } + /** + * Accessor to compute the hashed authentication token + * + * @param string $login user login + * @param string $token_auth authentication token + * @return string hashed authentication token + */ + public function getHashTokenAuth($login, $token_auth) + { + return md5($login . $token_auth); + } } diff --git a/plugins/Login/Controller.php b/plugins/Login/Controller.php index 7031ca4307..912c5f441d 100644 --- a/plugins/Login/Controller.php +++ b/plugins/Login/Controller.php @@ -16,510 +16,470 @@ */ class Piwik_Login_Controller extends Piwik_Controller { - /** - * Generate hash on user info and password - * - * @param string $userinfo User name, email, etc - * @param string $password - * @return string - */ - private function generateHash($userInfo, $password) - { - // mitigate rainbow table attack - $passwordLen = strlen($password) / 2; - $hash = Piwik_Common::hash( - $userInfo . substr($password, 0, $passwordLen) - . Piwik_Common::getSalt() . substr($password, $passwordLen) - ); - return $hash; - } - - /** - * Default action - * - * @param none - * @return void - */ - function index() - { - $this->login(); - } - - /** - * Login form - * - * @param string $messageNoAccess Access error message - * @param string $currentUrl Current URL - * @return void - */ - function login($messageNoAccess = null, $infoMessage = false) - { - self::checkForceSslLogin(); - - $form = new Piwik_Login_FormLogin(); - if($form->validate()) - { - $nonce = $form->getSubmitValue('form_nonce'); - if(Piwik_Nonce::verifyNonce('Piwik_Login.login', $nonce)) - { - $login = $form->getSubmitValue('form_login'); - $password = $form->getSubmitValue('form_password'); - $rememberMe = $form->getSubmitValue('form_rememberme') == '1'; - $md5Password = md5($password); - try { - $this->authenticateAndRedirect($login, $md5Password, $rememberMe); - } catch(Exception $e) { - $messageNoAccess = $e->getMessage(); - } - } - else - { - $messageNoAccess = $this->getMessageExceptionNoAccess(); - } - } - - $view = Piwik_View::factory('login'); - $view->AccessErrorString = $messageNoAccess; - $view->infoMessage = nl2br($infoMessage); - $view->addForm( $form ); - $this->configureView($view); - self::setHostValidationVariablesView($view); - echo $view->render(); - } - - /** - * Configure common view properties - * - * @param Piwik_View $view - */ - private function configureView($view) - { - $this->setBasicVariablesView($view); - - $view->linkTitle = Piwik::getRandomTitle(); - - $view->forceSslLogin = Piwik_Config::getInstance()->General['force_ssl_login']; - - // crsf token: don't trust the submitted value; generate/fetch it from session data - $view->nonce = Piwik_Nonce::getNonce('Piwik_Login.login'); - } - - /** - * Form-less login - * @see how to use it on http://piwik.org/faq/how-to/#faq_30 - * @throws Exception - * @return void - */ - function logme() - { - self::checkForceSslLogin(); - - $password = Piwik_Common::getRequestVar('password', null, 'string'); - if(strlen($password) != 32) - { - throw new Exception(Piwik_TranslateException('Login_ExceptionPasswordMD5HashExpected')); - } - - $login = Piwik_Common::getRequestVar('login', null, 'string'); - if($login == Piwik_Config::getInstance()->superuser['login']) - { - throw new Exception(Piwik_TranslateException('Login_ExceptionInvalidSuperUserAuthenticationMethod', array("logme"))); - } - - $currentUrl = 'index.php'; - - if(($idSite = Piwik_Common::getRequestVar('idSite', false, 'int')) !== false) - { - $currentUrl .= '?idSite='.$idSite; - } - - $urlToRedirect = Piwik_Common::getRequestVar('url', $currentUrl, 'string'); - $urlToRedirect = Piwik_Common::unsanitizeInputValue($urlToRedirect); - - $this->authenticateAndRedirect($login, $password, false, $urlToRedirect); - } - - /** - * Authenticate user and password. Redirect if successful. - * - * @param string $login user name - * @param string $md5Password md5 hash of password - * @param bool $rememberMe Remember me? - * @param string $urlToRedirect URL to redirect to, if successfully authenticated - * @return string failure message if unable to authenticate - */ - protected function authenticateAndRedirect($login, $md5Password, $rememberMe, $urlToRedirect = 'index.php') - { - $info = array( 'login' => $login, - 'md5Password' => $md5Password, - 'rememberMe' => $rememberMe, - ); - Piwik_Nonce::discardNonce('Piwik_Login.login'); - Piwik_PostEvent('Login.initSession', $info); - Piwik_Url::redirectToUrl($urlToRedirect); - } - - protected function getMessageExceptionNoAccess() - { - $message = Piwik_Translate('Login_InvalidNonceOrHeadersOrReferer', array('', '')); - // Should mention trusted_hosts or link to FAQ - return $message; - } - - /** - * Reset password action. Stores new password as hash and sends email - * to confirm use. - * - * @param none - * @return void - */ - function resetPassword() - { - self::checkForceSslLogin(); - - $infoMessage = null; - $formErrors = null; - - $form = new Piwik_Login_FormResetPassword(); - if($form->validate()) - { - $nonce = $form->getSubmitValue('form_nonce'); - if(Piwik_Nonce::verifyNonce('Piwik_Login.login', $nonce)) - { - $formErrors = $this->resetPasswordFirstStep($form); - if (empty($formErrors)) - { - $infoMessage = Piwik_Translate('Login_ConfirmationLinkSent'); - } - } - else - { - $formErrors = array($this->getMessageExceptionNoAccess()); - } - } - else - { - // if invalid, display error - $formData = $form->getFormData(); - $formErrors = $formData['errors']; - } - - $view = Piwik_View::factory('message'); - $view->infoMessage = $infoMessage; - $view->formErrors = $formErrors; - echo $view->render(); - } - - /** - * Saves password reset info and sends confirmation email. - * - * @return array Error message(s) if an error occurs. - */ - private function resetPasswordFirstStep( $form ) - { - $loginMail = $form->getSubmitValue('form_login'); - $token = $form->getSubmitValue('form_token'); - $password = $form->getSubmitValue('form_password'); - - // check the password - try - { - Piwik_UsersManager::checkPassword($password); - } - catch (Exception $ex) - { - return array($ex->getMessage()); - } - - // get the user's login - if ($loginMail === 'anonymous') - { - return array(Piwik_Translate('Login_InvalidUsernameEmail')); - } - - $user = self::getUserInformation($loginMail); - if ($user === null) - { - return array(Piwik_Translate('Login_InvalidUsernameEmail')); - } - - $login = $user['login']; - - // if valid, store password information in options table, then... - Piwik_Login::savePasswordResetInfo($login, $password); - - // ... send email with confirmation link - try - { - $this->sendEmailConfirmationLink($user); - } - catch (Exception $ex) - { - // remove password reset info - Piwik_Login::removePasswordResetInfo($login); - - return array($ex->getMessage().'
'.Piwik_Translate('Login_ContactAdmin')); - } - - return null; - } - - /** - * Sends email confirmation link for a password reset request. - * - * @param array $user User info for the requested password reset. - */ - private function sendEmailConfirmationLink( $user ) - { - $login = $user['login']; - $email = $user['email']; - - // construct a password reset token from user information - $resetToken = self::generatePasswordResetToken($user); - - $ip = Piwik_IP::getIpFromHeader(); - $url = Piwik_Url::getCurrentUrlWithoutQueryString() - . "?module=Login&action=confirmResetPassword&login=".urlencode($login) - . "&resetToken=".urlencode($resetToken); - - // send email with new password - $mail = new Piwik_Mail(); - $mail->addTo($email, $login); - $mail->setSubject(Piwik_Translate('Login_MailTopicPasswordChange')); - $bodyText = str_replace( - '\n', - "\n", - sprintf(Piwik_Translate('Login_MailPasswordChangeBody'), $login, $ip, $url) - ) . "\n"; - $mail->setBodyText($bodyText); - - $fromEmailName = Piwik_Config::getInstance()->General['login_password_recovery_email_name']; - $fromEmailAddress = Piwik_Config::getInstance()->General['login_password_recovery_email_address']; - $mail->setFrom($fromEmailAddress, $fromEmailName); - @$mail->send(); - } - - /** - * Password reset confirmation action. Finishes the password reset process. - * Users visit this action from a link supplied in an email. - */ - public function confirmResetPassword() - { - $errorMessage = null; - - $login = Piwik_Common::getRequestVar('login', ''); - $resetToken = Piwik_Common::getRequestVar('resetToken', ''); - - try - { - // get password reset info & user info - $user = self::getUserInformation($login); - if ($user === null) - { - throw new Exception(Piwik_Translate('Login_InvalidUsernameEmail')); - } - - // check that the reset token is valid - $resetPassword = Piwik_Login::getPasswordToResetTo($login); - if ($resetPassword === false || !self::isValidToken($resetToken, $user)) - { - throw new Exception(Piwik_Translate('Login_InvalidOrExpiredToken')); - } - - // reset password of user - $this->setNewUserPassword($user, $resetPassword); - } - catch (Exception $ex) - { - $errorMessage = $ex->getMessage(); - } - - if (is_null($errorMessage)) // if success, show login w/ success message - { - $this->redirectToIndex('Login', 'resetPasswordSuccess'); - } - else - { - // show login page w/ error. this will keep the token in the URL - return $this->login($errorMessage); - } - } - - /** - * Sets the password for a user. - * - * @param array $user User info. - * @param string $passwordHash The hashed password to use. - */ - private function setNewUserPassword( $user, $passwordHash ) - { - if (strlen($passwordHash) !== 32) // sanity check - { - throw new Exception( - "setNewUserPassword called w/ incorrect password hash. Something has gone terribly wrong."); - } - - if( $user['email'] == Piwik::getSuperUserEmail() ) - { - if(!Piwik_Config::getInstance()->isFileWritable()) - { - throw new Exception(Piwik_Translate('General_ConfigFileIsNotWritable', array("(config/config.ini.php)","
"))); - } - - $user['password'] = $passwordHash; - Piwik_Config::getInstance()->superuser = $user; - Piwik_Config::getInstance()->forceSave(); - } - else - { - Piwik_UsersManager_API::getInstance()->updateUser( - $user['login'], $passwordHash, $email = false, $alias = false, $isPasswordHashed = true); - } - } - - /** - * The action used after a password is successfully reset. Displays the login - * screen with an extra message. A separate action is used instead of returning - * the HTML in confirmResetPassword so the resetToken won't be in the URL. - */ - public function resetPasswordSuccess() - { - return $this->login($errorMessage = null, $infoMessage = Piwik_Translate('Login_PasswordChanged')); - } - - /** - * Get user information - * - * @param string $loginMail user login or email address - * @return array ("login" => '...', "email" => '...', "password" => '...') or null, if user not found - */ - protected function getUserInformation($loginMail) - { - Piwik::setUserIsSuperUser(); - - $user = null; - if( $loginMail == Piwik::getSuperUserEmail() - || $loginMail == Piwik_Config::getInstance()->superuser['login'] ) - { - $user = array( - 'login' => Piwik_Config::getInstance()->superuser['login'], - 'email' => Piwik::getSuperUserEmail(), - 'password' => Piwik_Config::getInstance()->superuser['password'], - ); - } - else if( Piwik_UsersManager_API::getInstance()->userExists($loginMail) ) - { - $user = Piwik_UsersManager_API::getInstance()->getUser($loginMail); - } - else if( Piwik_UsersManager_API::getInstance()->userEmailExists($loginMail) ) - { - $user = Piwik_UsersManager_API::getInstance()->getUserByEmail($loginMail); - } - - return $user; - } - - /** - * Generate a password reset token. Expires in (roughly) 24 hours. - * - * @param array user information - * @param int $timestamp Unix timestamp - * @return string generated token - */ - protected function generatePasswordResetToken($user, $timestamp = null) - { - /* - * Piwik does not store the generated password reset token. - * This avoids a database schema change and SQL queries to store, retrieve, and purge (expired) tokens. - */ - if(!$timestamp) - { - $timestamp = time() + 24*60*60; /* +24 hrs */ - } - - $expiry = strftime('%Y%m%d%H', $timestamp); - $token = $this->generateHash( - $expiry . $user['login'] . $user['email'], - $user['password'] - ); - return $token; - } - - /** - * Validate token. - * - * @param string $token - * @param array $user user information - * @return bool true if valid, false otherwise - */ - protected function isValidToken($token, $user) - { - $now = time(); - - // token valid for 24 hrs (give or take, due to the coarse granularity in our strftime format string) - for($i = 0; $i <= 24; $i++) - { - $generatedToken = self::generatePasswordResetToken($user, $now + $i*60*60); - if($generatedToken === $token) - { - return true; - } - } - - // fails if token is invalid, expired, password already changed, other user information has changed, ... - return false; - } - - /** - * Clear session information - * - * @param none - * @return void - */ - static public function clearSession() - { - $authCookieName = Piwik_Config::getInstance()->General['login_cookie_name']; - $cookie = new Piwik_Cookie($authCookieName); - $cookie->delete(); - - Piwik_Session::expireSessionCookie(); - } - - /** - * Logout current user - * - * @param none - * @return void - */ - public function logout() - { - self::clearSession(); - - $logoutUrl = @Piwik_Config::getInstance()->General['login_logout_url']; - if(empty($logoutUrl)) { - Piwik::redirectToModule('CoreHome'); - } else { - Piwik_Url::redirectToUrl($logoutUrl); - } - } - - /** - * Check force_ssl_login and redirect if connection isn't secure and not using a reverse proxy - * - * @param none - * @return void - */ - protected function checkForceSslLogin() - { - $forceSslLogin = Piwik_Config::getInstance()->General['force_ssl_login']; - if($forceSslLogin - && !Piwik::isHttps()) - { - $url = 'https://' - . Piwik_Url::getCurrentHost() - . Piwik_Url::getCurrentScriptName() - . Piwik_Url::getCurrentQueryString(); - Piwik_Url::redirectToUrl($url); - } - } + /** + * Generate hash on user info and password + * + * @param string $userinfo User name, email, etc + * @param string $password + * @return string + */ + private function generateHash($userInfo, $password) + { + // mitigate rainbow table attack + $passwordLen = strlen($password) / 2; + $hash = Piwik_Common::hash( + $userInfo . substr($password, 0, $passwordLen) + . Piwik_Common::getSalt() . substr($password, $passwordLen) + ); + return $hash; + } + + /** + * Default action + * + * @param none + * @return void + */ + function index() + { + $this->login(); + } + + /** + * Login form + * + * @param string $messageNoAccess Access error message + * @param string $currentUrl Current URL + * @return void + */ + function login($messageNoAccess = null, $infoMessage = false) + { + self::checkForceSslLogin(); + + $form = new Piwik_Login_FormLogin(); + if ($form->validate()) { + $nonce = $form->getSubmitValue('form_nonce'); + if (Piwik_Nonce::verifyNonce('Piwik_Login.login', $nonce)) { + $login = $form->getSubmitValue('form_login'); + $password = $form->getSubmitValue('form_password'); + $rememberMe = $form->getSubmitValue('form_rememberme') == '1'; + $md5Password = md5($password); + try { + $this->authenticateAndRedirect($login, $md5Password, $rememberMe); + } catch (Exception $e) { + $messageNoAccess = $e->getMessage(); + } + } else { + $messageNoAccess = $this->getMessageExceptionNoAccess(); + } + } + + $view = Piwik_View::factory('login'); + $view->AccessErrorString = $messageNoAccess; + $view->infoMessage = nl2br($infoMessage); + $view->addForm($form); + $this->configureView($view); + self::setHostValidationVariablesView($view); + echo $view->render(); + } + + /** + * Configure common view properties + * + * @param Piwik_View $view + */ + private function configureView($view) + { + $this->setBasicVariablesView($view); + + $view->linkTitle = Piwik::getRandomTitle(); + + $view->forceSslLogin = Piwik_Config::getInstance()->General['force_ssl_login']; + + // crsf token: don't trust the submitted value; generate/fetch it from session data + $view->nonce = Piwik_Nonce::getNonce('Piwik_Login.login'); + } + + /** + * Form-less login + * @see how to use it on http://piwik.org/faq/how-to/#faq_30 + * @throws Exception + * @return void + */ + function logme() + { + self::checkForceSslLogin(); + + $password = Piwik_Common::getRequestVar('password', null, 'string'); + if (strlen($password) != 32) { + throw new Exception(Piwik_TranslateException('Login_ExceptionPasswordMD5HashExpected')); + } + + $login = Piwik_Common::getRequestVar('login', null, 'string'); + if ($login == Piwik_Config::getInstance()->superuser['login']) { + throw new Exception(Piwik_TranslateException('Login_ExceptionInvalidSuperUserAuthenticationMethod', array("logme"))); + } + + $currentUrl = 'index.php'; + + if (($idSite = Piwik_Common::getRequestVar('idSite', false, 'int')) !== false) { + $currentUrl .= '?idSite=' . $idSite; + } + + $urlToRedirect = Piwik_Common::getRequestVar('url', $currentUrl, 'string'); + $urlToRedirect = Piwik_Common::unsanitizeInputValue($urlToRedirect); + + $this->authenticateAndRedirect($login, $password, false, $urlToRedirect); + } + + /** + * Authenticate user and password. Redirect if successful. + * + * @param string $login user name + * @param string $md5Password md5 hash of password + * @param bool $rememberMe Remember me? + * @param string $urlToRedirect URL to redirect to, if successfully authenticated + * @return string failure message if unable to authenticate + */ + protected function authenticateAndRedirect($login, $md5Password, $rememberMe, $urlToRedirect = 'index.php') + { + $info = array('login' => $login, + 'md5Password' => $md5Password, + 'rememberMe' => $rememberMe, + ); + Piwik_Nonce::discardNonce('Piwik_Login.login'); + Piwik_PostEvent('Login.initSession', $info); + Piwik_Url::redirectToUrl($urlToRedirect); + } + + protected function getMessageExceptionNoAccess() + { + $message = Piwik_Translate('Login_InvalidNonceOrHeadersOrReferer', array('', '')); + // Should mention trusted_hosts or link to FAQ + return $message; + } + + /** + * Reset password action. Stores new password as hash and sends email + * to confirm use. + * + * @param none + * @return void + */ + function resetPassword() + { + self::checkForceSslLogin(); + + $infoMessage = null; + $formErrors = null; + + $form = new Piwik_Login_FormResetPassword(); + if ($form->validate()) { + $nonce = $form->getSubmitValue('form_nonce'); + if (Piwik_Nonce::verifyNonce('Piwik_Login.login', $nonce)) { + $formErrors = $this->resetPasswordFirstStep($form); + if (empty($formErrors)) { + $infoMessage = Piwik_Translate('Login_ConfirmationLinkSent'); + } + } else { + $formErrors = array($this->getMessageExceptionNoAccess()); + } + } else { + // if invalid, display error + $formData = $form->getFormData(); + $formErrors = $formData['errors']; + } + + $view = Piwik_View::factory('message'); + $view->infoMessage = $infoMessage; + $view->formErrors = $formErrors; + echo $view->render(); + } + + /** + * Saves password reset info and sends confirmation email. + * + * @return array Error message(s) if an error occurs. + */ + private function resetPasswordFirstStep($form) + { + $loginMail = $form->getSubmitValue('form_login'); + $token = $form->getSubmitValue('form_token'); + $password = $form->getSubmitValue('form_password'); + + // check the password + try { + Piwik_UsersManager::checkPassword($password); + } catch (Exception $ex) { + return array($ex->getMessage()); + } + + // get the user's login + if ($loginMail === 'anonymous') { + return array(Piwik_Translate('Login_InvalidUsernameEmail')); + } + + $user = self::getUserInformation($loginMail); + if ($user === null) { + return array(Piwik_Translate('Login_InvalidUsernameEmail')); + } + + $login = $user['login']; + + // if valid, store password information in options table, then... + Piwik_Login::savePasswordResetInfo($login, $password); + + // ... send email with confirmation link + try { + $this->sendEmailConfirmationLink($user); + } catch (Exception $ex) { + // remove password reset info + Piwik_Login::removePasswordResetInfo($login); + + return array($ex->getMessage() . '
' . Piwik_Translate('Login_ContactAdmin')); + } + + return null; + } + + /** + * Sends email confirmation link for a password reset request. + * + * @param array $user User info for the requested password reset. + */ + private function sendEmailConfirmationLink($user) + { + $login = $user['login']; + $email = $user['email']; + + // construct a password reset token from user information + $resetToken = self::generatePasswordResetToken($user); + + $ip = Piwik_IP::getIpFromHeader(); + $url = Piwik_Url::getCurrentUrlWithoutQueryString() + . "?module=Login&action=confirmResetPassword&login=" . urlencode($login) + . "&resetToken=" . urlencode($resetToken); + + // send email with new password + $mail = new Piwik_Mail(); + $mail->addTo($email, $login); + $mail->setSubject(Piwik_Translate('Login_MailTopicPasswordChange')); + $bodyText = str_replace( + '\n', + "\n", + sprintf(Piwik_Translate('Login_MailPasswordChangeBody'), $login, $ip, $url) + ) . "\n"; + $mail->setBodyText($bodyText); + + $fromEmailName = Piwik_Config::getInstance()->General['login_password_recovery_email_name']; + $fromEmailAddress = Piwik_Config::getInstance()->General['login_password_recovery_email_address']; + $mail->setFrom($fromEmailAddress, $fromEmailName); + @$mail->send(); + } + + /** + * Password reset confirmation action. Finishes the password reset process. + * Users visit this action from a link supplied in an email. + */ + public function confirmResetPassword() + { + $errorMessage = null; + + $login = Piwik_Common::getRequestVar('login', ''); + $resetToken = Piwik_Common::getRequestVar('resetToken', ''); + + try { + // get password reset info & user info + $user = self::getUserInformation($login); + if ($user === null) { + throw new Exception(Piwik_Translate('Login_InvalidUsernameEmail')); + } + + // check that the reset token is valid + $resetPassword = Piwik_Login::getPasswordToResetTo($login); + if ($resetPassword === false || !self::isValidToken($resetToken, $user)) { + throw new Exception(Piwik_Translate('Login_InvalidOrExpiredToken')); + } + + // reset password of user + $this->setNewUserPassword($user, $resetPassword); + } catch (Exception $ex) { + $errorMessage = $ex->getMessage(); + } + + if (is_null($errorMessage)) // if success, show login w/ success message + { + $this->redirectToIndex('Login', 'resetPasswordSuccess'); + } else { + // show login page w/ error. this will keep the token in the URL + return $this->login($errorMessage); + } + } + + /** + * Sets the password for a user. + * + * @param array $user User info. + * @param string $passwordHash The hashed password to use. + */ + private function setNewUserPassword($user, $passwordHash) + { + if (strlen($passwordHash) !== 32) // sanity check + { + throw new Exception( + "setNewUserPassword called w/ incorrect password hash. Something has gone terribly wrong."); + } + + if ($user['email'] == Piwik::getSuperUserEmail()) { + if (!Piwik_Config::getInstance()->isFileWritable()) { + throw new Exception(Piwik_Translate('General_ConfigFileIsNotWritable', array("(config/config.ini.php)", "
"))); + } + + $user['password'] = $passwordHash; + Piwik_Config::getInstance()->superuser = $user; + Piwik_Config::getInstance()->forceSave(); + } else { + Piwik_UsersManager_API::getInstance()->updateUser( + $user['login'], $passwordHash, $email = false, $alias = false, $isPasswordHashed = true); + } + } + + /** + * The action used after a password is successfully reset. Displays the login + * screen with an extra message. A separate action is used instead of returning + * the HTML in confirmResetPassword so the resetToken won't be in the URL. + */ + public function resetPasswordSuccess() + { + return $this->login($errorMessage = null, $infoMessage = Piwik_Translate('Login_PasswordChanged')); + } + + /** + * Get user information + * + * @param string $loginMail user login or email address + * @return array ("login" => '...', "email" => '...', "password" => '...') or null, if user not found + */ + protected function getUserInformation($loginMail) + { + Piwik::setUserIsSuperUser(); + + $user = null; + if ($loginMail == Piwik::getSuperUserEmail() + || $loginMail == Piwik_Config::getInstance()->superuser['login'] + ) { + $user = array( + 'login' => Piwik_Config::getInstance()->superuser['login'], + 'email' => Piwik::getSuperUserEmail(), + 'password' => Piwik_Config::getInstance()->superuser['password'], + ); + } else if (Piwik_UsersManager_API::getInstance()->userExists($loginMail)) { + $user = Piwik_UsersManager_API::getInstance()->getUser($loginMail); + } else if (Piwik_UsersManager_API::getInstance()->userEmailExists($loginMail)) { + $user = Piwik_UsersManager_API::getInstance()->getUserByEmail($loginMail); + } + + return $user; + } + + /** + * Generate a password reset token. Expires in (roughly) 24 hours. + * + * @param array user information + * @param int $timestamp Unix timestamp + * @return string generated token + */ + protected function generatePasswordResetToken($user, $timestamp = null) + { + /* + * Piwik does not store the generated password reset token. + * This avoids a database schema change and SQL queries to store, retrieve, and purge (expired) tokens. + */ + if (!$timestamp) { + $timestamp = time() + 24 * 60 * 60; /* +24 hrs */ + } + + $expiry = strftime('%Y%m%d%H', $timestamp); + $token = $this->generateHash( + $expiry . $user['login'] . $user['email'], + $user['password'] + ); + return $token; + } + + /** + * Validate token. + * + * @param string $token + * @param array $user user information + * @return bool true if valid, false otherwise + */ + protected function isValidToken($token, $user) + { + $now = time(); + + // token valid for 24 hrs (give or take, due to the coarse granularity in our strftime format string) + for ($i = 0; $i <= 24; $i++) { + $generatedToken = self::generatePasswordResetToken($user, $now + $i * 60 * 60); + if ($generatedToken === $token) { + return true; + } + } + + // fails if token is invalid, expired, password already changed, other user information has changed, ... + return false; + } + + /** + * Clear session information + * + * @param none + * @return void + */ + static public function clearSession() + { + $authCookieName = Piwik_Config::getInstance()->General['login_cookie_name']; + $cookie = new Piwik_Cookie($authCookieName); + $cookie->delete(); + + Piwik_Session::expireSessionCookie(); + } + + /** + * Logout current user + * + * @param none + * @return void + */ + public function logout() + { + self::clearSession(); + + $logoutUrl = @Piwik_Config::getInstance()->General['login_logout_url']; + if (empty($logoutUrl)) { + Piwik::redirectToModule('CoreHome'); + } else { + Piwik_Url::redirectToUrl($logoutUrl); + } + } + + /** + * Check force_ssl_login and redirect if connection isn't secure and not using a reverse proxy + * + * @param none + * @return void + */ + protected function checkForceSslLogin() + { + $forceSslLogin = Piwik_Config::getInstance()->General['force_ssl_login']; + if ($forceSslLogin + && !Piwik::isHttps() + ) { + $url = 'https://' + . Piwik_Url::getCurrentHost() + . Piwik_Url::getCurrentScriptName() + . Piwik_Url::getCurrentQueryString(); + Piwik_Url::redirectToUrl($url); + } + } } diff --git a/plugins/Login/FormLogin.php b/plugins/Login/FormLogin.php index 46c02f2f91..a90146f47e 100644 --- a/plugins/Login/FormLogin.php +++ b/plugins/Login/FormLogin.php @@ -15,28 +15,28 @@ */ class Piwik_Login_FormLogin extends Piwik_QuickForm2 { - function __construct( $id = 'login_form', $method = 'post', $attributes = null, $trackSubmit = false) - { - parent::__construct($id, $method, $attributes, $trackSubmit); - } + function __construct($id = 'login_form', $method = 'post', $attributes = null, $trackSubmit = false) + { + parent::__construct($id, $method, $attributes, $trackSubmit); + } - function init() - { - $this->addElement('text', 'form_login') - ->addRule('required', Piwik_Translate('General_Required', Piwik_Translate('General_Username'))); + function init() + { + $this->addElement('text', 'form_login') + ->addRule('required', Piwik_Translate('General_Required', Piwik_Translate('General_Username'))); - $this->addElement('password', 'form_password') - ->addRule('required', Piwik_Translate('General_Required', Piwik_Translate('Login_Password'))); + $this->addElement('password', 'form_password') + ->addRule('required', Piwik_Translate('General_Required', Piwik_Translate('Login_Password'))); - $this->addElement('hidden', 'form_nonce'); + $this->addElement('hidden', 'form_nonce'); - $this->addElement('checkbox', 'form_rememberme'); + $this->addElement('checkbox', 'form_rememberme'); - $this->addElement('submit', 'submit'); + $this->addElement('submit', 'submit'); - // default values - $this->addDataSource(new HTML_QuickForm2_DataSource_Array(array( - 'form_rememberme' => 0, - ))); - } + // default values + $this->addDataSource(new HTML_QuickForm2_DataSource_Array(array( + 'form_rememberme' => 0, + ))); + } } diff --git a/plugins/Login/FormResetPassword.php b/plugins/Login/FormResetPassword.php index 88791060d4..0411beddbb 100644 --- a/plugins/Login/FormResetPassword.php +++ b/plugins/Login/FormResetPassword.php @@ -15,25 +15,25 @@ */ class Piwik_Login_FormResetPassword extends Piwik_QuickForm2 { - function __construct( $id = 'resetpasswordform', $method = 'post', $attributes = null, $trackSubmit = false) - { - parent::__construct($id, $method, $attributes, $trackSubmit); - } + function __construct($id = 'resetpasswordform', $method = 'post', $attributes = null, $trackSubmit = false) + { + parent::__construct($id, $method, $attributes, $trackSubmit); + } - function init() - { - $this->addElement('text', 'form_login') - ->addRule('required', Piwik_Translate('General_Required', Piwik_Translate('General_Username'))); + function init() + { + $this->addElement('text', 'form_login') + ->addRule('required', Piwik_Translate('General_Required', Piwik_Translate('General_Username'))); - $password = $this->addElement('password', 'form_password'); - $password->addRule('required', Piwik_Translate('General_Required', Piwik_Translate('Login_Password'))); + $password = $this->addElement('password', 'form_password'); + $password->addRule('required', Piwik_Translate('General_Required', Piwik_Translate('Login_Password'))); - $passwordBis = $this->addElement('password', 'form_password_bis'); - $passwordBis->addRule('required', Piwik_Translate('General_Required', Piwik_Translate('Login_PasswordRepeat'))); - $passwordBis->addRule('eq', Piwik_Translate( 'Login_PasswordsDoNotMatch'), $password); + $passwordBis = $this->addElement('password', 'form_password_bis'); + $passwordBis->addRule('required', Piwik_Translate('General_Required', Piwik_Translate('Login_PasswordRepeat'))); + $passwordBis->addRule('eq', Piwik_Translate('Login_PasswordsDoNotMatch'), $password); - $this->addElement('hidden', 'form_nonce'); + $this->addElement('hidden', 'form_nonce'); - $this->addElement('submit', 'submit'); - } + $this->addElement('submit', 'submit'); + } } diff --git a/plugins/Login/Login.php b/plugins/Login/Login.php index e56c4560e2..5b92eaca87 100644 --- a/plugins/Login/Login.php +++ b/plugins/Login/Login.php @@ -15,183 +15,180 @@ */ class Piwik_Login extends Piwik_Plugin { - public function getInformation() - { - $info = array( - 'description' => Piwik_Translate('Login_PluginDescription'), - 'author' => 'Piwik', - 'author_homepage' => 'http://piwik.org/', - 'version' => Piwik_Version::VERSION, - ); - return $info; - } - - function getListHooksRegistered() - { - $hooks = array( - 'FrontController.initAuthenticationObject' => 'initAuthenticationObject', - 'FrontController.NoAccessException' => 'noAccess', - 'API.Request.authenticate' => 'ApiRequestAuthenticate', - 'Login.initSession' => 'initSession', - ); - return $hooks; - } - - /** - * Redirects to Login form with error message. - * Listens to FrontController.NoAccessException hook. - * - * @param Piwik_Event_Notification $notification notification object - */ - function noAccess( $notification ) - { - /* @var Exception $exception */ - $exception = $notification->getNotificationObject(); - $exceptionMessage = $exception->getMessage(); - - $controller = new Piwik_Login_Controller(); - $controller->login($exceptionMessage, '' /* $exception->getTraceAsString() */ ); - } - - /** - * Set login name and autehntication token for authentication request. - * Listens to API.Request.authenticate hook. - * - * @param Piwik_Event_Notification $notification notification object - */ - function ApiRequestAuthenticate($notification) - { - $tokenAuth = $notification->getNotificationObject(); - Zend_Registry::get('auth')->setLogin($login = null); - Zend_Registry::get('auth')->setTokenAuth($tokenAuth); - } - - /** - * Initializes the authentication object. - * Listens to FrontController.initAuthenticationObject hook. - * - * @param Piwik_Event_Notification $notification notification object - */ - function initAuthenticationObject($notification) - { - $auth = new Piwik_Login_Auth(); - Zend_Registry::set('auth', $auth); - - $allowCookieAuthentication = $notification->getNotificationInfo(); - - $action = Piwik::getAction(); - if (Piwik::getModule() === 'API' - && (empty($action) || $action == 'index') - && $allowCookieAuthentication !== true) - { - return; - } - - $authCookieName = Piwik_Config::getInstance()->General['login_cookie_name']; - $authCookieExpiry = 0; - $authCookiePath = Piwik_Config::getInstance()->General['login_cookie_path']; - $authCookie = new Piwik_Cookie($authCookieName, $authCookieExpiry, $authCookiePath); - $defaultLogin = 'anonymous'; - $defaultTokenAuth = 'anonymous'; - if($authCookie->isCookieFound()) - { - $defaultLogin = $authCookie->get('login'); - $defaultTokenAuth = $authCookie->get('token_auth'); - } - $auth->setLogin($defaultLogin); - $auth->setTokenAuth($defaultTokenAuth); - } - - /** - * Authenticate user and initializes the session. - * Listens to Login.initSession hook. - * - * @param Piwik_Event_Notification $notification notification object - * @throws Exception - */ - function initSession($notification) - { - $info = $notification->getNotificationObject(); - $login = $info['login']; - $md5Password = $info['md5Password']; - $rememberMe = $info['rememberMe']; - - $tokenAuth = Piwik_UsersManager_API::getInstance()->getTokenAuth($login, $md5Password); - - $auth = Zend_Registry::get('auth'); - $auth->setLogin($login); - $auth->setTokenAuth($tokenAuth); - $authResult = $auth->authenticate(); - - $authCookieName = Piwik_Config::getInstance()->General['login_cookie_name']; - $authCookieExpiry = $rememberMe ? time() + Piwik_Config::getInstance()->General['login_cookie_expire'] : 0; - $authCookiePath = Piwik_Config::getInstance()->General['login_cookie_path']; - $cookie = new Piwik_Cookie($authCookieName, $authCookieExpiry, $authCookiePath); - if(!$authResult->isValid()) - - { - $cookie->delete(); - throw new Exception(Piwik_Translate('Login_LoginPasswordNotCorrect')); - } - - $cookie->set('login', $login); - $cookie->set('token_auth', $auth->getHashTokenAuth($login, $authResult->getTokenAuth())); - $cookie->setSecure(Piwik::isHttps()); - $cookie->setHttpOnly(true); - $cookie->save(); - - @Piwik_Session::regenerateId(); - - // remove password reset entry if it exists - self::removePasswordResetInfo($login); - } - - /** - * Stores password reset info for a specific login. - * - * @param string $login The user login for whom a password change was requested. - * @param string $password The new password to set. - */ - public static function savePasswordResetInfo( $login, $password ) - { - $optionName = self::getPasswordResetInfoOptionName($login); - $optionData = Piwik_UsersManager::getPasswordHash($password); - - Piwik_SetOption($optionName, $optionData); - } - - /** - * Removes stored password reset info if it exists. - * - * @param string $login The user login to check for. - */ - public static function removePasswordResetInfo( $login ) - { - $optionName = self::getPasswordResetInfoOptionName($login); - Piwik_Option::getInstance()->delete($optionName); - } - - /** - * Gets password hash stored in password reset info. - * - * @param string $login The user login to check for. - * @return string|false The hashed password or false if no reset info exists. - */ - public static function getPasswordToResetTo( $login ) - { - $optionName = self::getPasswordResetInfoOptionName($login); - return Piwik_GetOption($optionName); - } - - /** - * Gets the option name for the option that will store a user's password change - * request. - * - * @param string $login The user login for whom a password change was requested. - * @return string - */ - public static function getPasswordResetInfoOptionName( $login ) - { - return $login.'_reset_password_info'; - } + public function getInformation() + { + $info = array( + 'description' => Piwik_Translate('Login_PluginDescription'), + 'author' => 'Piwik', + 'author_homepage' => 'http://piwik.org/', + 'version' => Piwik_Version::VERSION, + ); + return $info; + } + + function getListHooksRegistered() + { + $hooks = array( + 'FrontController.initAuthenticationObject' => 'initAuthenticationObject', + 'FrontController.NoAccessException' => 'noAccess', + 'API.Request.authenticate' => 'ApiRequestAuthenticate', + 'Login.initSession' => 'initSession', + ); + return $hooks; + } + + /** + * Redirects to Login form with error message. + * Listens to FrontController.NoAccessException hook. + * + * @param Piwik_Event_Notification $notification notification object + */ + function noAccess($notification) + { + /* @var Exception $exception */ + $exception = $notification->getNotificationObject(); + $exceptionMessage = $exception->getMessage(); + + $controller = new Piwik_Login_Controller(); + $controller->login($exceptionMessage, '' /* $exception->getTraceAsString() */); + } + + /** + * Set login name and autehntication token for authentication request. + * Listens to API.Request.authenticate hook. + * + * @param Piwik_Event_Notification $notification notification object + */ + function ApiRequestAuthenticate($notification) + { + $tokenAuth = $notification->getNotificationObject(); + Zend_Registry::get('auth')->setLogin($login = null); + Zend_Registry::get('auth')->setTokenAuth($tokenAuth); + } + + /** + * Initializes the authentication object. + * Listens to FrontController.initAuthenticationObject hook. + * + * @param Piwik_Event_Notification $notification notification object + */ + function initAuthenticationObject($notification) + { + $auth = new Piwik_Login_Auth(); + Zend_Registry::set('auth', $auth); + + $allowCookieAuthentication = $notification->getNotificationInfo(); + + $action = Piwik::getAction(); + if (Piwik::getModule() === 'API' + && (empty($action) || $action == 'index') + && $allowCookieAuthentication !== true + ) { + return; + } + + $authCookieName = Piwik_Config::getInstance()->General['login_cookie_name']; + $authCookieExpiry = 0; + $authCookiePath = Piwik_Config::getInstance()->General['login_cookie_path']; + $authCookie = new Piwik_Cookie($authCookieName, $authCookieExpiry, $authCookiePath); + $defaultLogin = 'anonymous'; + $defaultTokenAuth = 'anonymous'; + if ($authCookie->isCookieFound()) { + $defaultLogin = $authCookie->get('login'); + $defaultTokenAuth = $authCookie->get('token_auth'); + } + $auth->setLogin($defaultLogin); + $auth->setTokenAuth($defaultTokenAuth); + } + + /** + * Authenticate user and initializes the session. + * Listens to Login.initSession hook. + * + * @param Piwik_Event_Notification $notification notification object + * @throws Exception + */ + function initSession($notification) + { + $info = $notification->getNotificationObject(); + $login = $info['login']; + $md5Password = $info['md5Password']; + $rememberMe = $info['rememberMe']; + + $tokenAuth = Piwik_UsersManager_API::getInstance()->getTokenAuth($login, $md5Password); + + $auth = Zend_Registry::get('auth'); + $auth->setLogin($login); + $auth->setTokenAuth($tokenAuth); + $authResult = $auth->authenticate(); + + $authCookieName = Piwik_Config::getInstance()->General['login_cookie_name']; + $authCookieExpiry = $rememberMe ? time() + Piwik_Config::getInstance()->General['login_cookie_expire'] : 0; + $authCookiePath = Piwik_Config::getInstance()->General['login_cookie_path']; + $cookie = new Piwik_Cookie($authCookieName, $authCookieExpiry, $authCookiePath); + if (!$authResult->isValid()) { + $cookie->delete(); + throw new Exception(Piwik_Translate('Login_LoginPasswordNotCorrect')); + } + + $cookie->set('login', $login); + $cookie->set('token_auth', $auth->getHashTokenAuth($login, $authResult->getTokenAuth())); + $cookie->setSecure(Piwik::isHttps()); + $cookie->setHttpOnly(true); + $cookie->save(); + + @Piwik_Session::regenerateId(); + + // remove password reset entry if it exists + self::removePasswordResetInfo($login); + } + + /** + * Stores password reset info for a specific login. + * + * @param string $login The user login for whom a password change was requested. + * @param string $password The new password to set. + */ + public static function savePasswordResetInfo($login, $password) + { + $optionName = self::getPasswordResetInfoOptionName($login); + $optionData = Piwik_UsersManager::getPasswordHash($password); + + Piwik_SetOption($optionName, $optionData); + } + + /** + * Removes stored password reset info if it exists. + * + * @param string $login The user login to check for. + */ + public static function removePasswordResetInfo($login) + { + $optionName = self::getPasswordResetInfoOptionName($login); + Piwik_Option::getInstance()->delete($optionName); + } + + /** + * Gets password hash stored in password reset info. + * + * @param string $login The user login to check for. + * @return string|false The hashed password or false if no reset info exists. + */ + public static function getPasswordToResetTo($login) + { + $optionName = self::getPasswordResetInfoOptionName($login); + return Piwik_GetOption($optionName); + } + + /** + * Gets the option name for the option that will store a user's password change + * request. + * + * @param string $login The user login for whom a password change was requested. + * @return string + */ + public static function getPasswordResetInfoOptionName($login) + { + return $login . '_reset_password_info'; + } } diff --git a/plugins/Login/templates/header.tpl b/plugins/Login/templates/header.tpl index 6b27f66710..e4e1919633 100644 --- a/plugins/Login/templates/header.tpl +++ b/plugins/Login/templates/header.tpl @@ -1,60 +1,64 @@ - - + + + - {if !$isCustomLogo}Piwik › {/if}{'Login_LogIn'|translate} - - - - - - - -{if isset($forceSslLogin) && $forceSslLogin} -{literal} - -{/literal} -{/if} -{literal} - -{/literal} - -{if 'General_LayoutDirection'|translate =='rtl'} - -{/if} -{include file="CoreHome/templates/iframe_buster_header.tpl"} + {if !$isCustomLogo}Piwik › {/if}{'Login_LogIn'|translate} + + + + + + + + {if isset($forceSslLogin) && $forceSslLogin} + {literal} + + {/literal} + {/if} + {literal} + + {/literal} + + {if 'General_LayoutDirection'|translate =='rtl'} + + {/if} + {include file="CoreHome/templates/iframe_buster_header.tpl"} {include file="CoreHome/templates/iframe_buster_body.tpl"} - + diff --git a/plugins/Login/templates/login.css b/plugins/Login/templates/login.css index d8c3f3d87f..7d62cea47a 100644 --- a/plugins/Login/templates/login.css +++ b/plugins/Login/templates/login.css @@ -1,227 +1,224 @@ /* shamelessly taken from wordpress 2.5 - thank you guys!!! */ * { - margin: 0; - padding: 0; + margin: 0; + padding: 0; } body { - font: 12px "Lucida Grande", "Lucida Sans Unicode", Tahoma, Verdana, sans-serif; + font: 12px "Lucida Grande", "Lucida Sans Unicode", Tahoma, Verdana, sans-serif; } form { - padding: 16px 16px 16px 16px; - border-radius: 5px; + padding: 16px 16px 16px 16px; + border-radius: 5px; } #login form input.submit { - font-family: "Lucida Grande", "Lucida Sans Unicode", Tahoma, Verdana, sans-serif; - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - float: right; - height: 35px; - padding: 0 20px; - cursor: pointer; - font: bold 15px Arial, Helvetica; + font-family: "Lucida Grande", "Lucida Sans Unicode", Tahoma, Verdana, sans-serif; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + float: right; + height: 35px; + padding: 0 20px; + cursor: pointer; + font: bold 15px Arial, Helvetica; } #login form div { - margin-bottom: 24px; + margin-bottom: 24px; } -.updated,.login #login_error,.login .message { - background-color: #ffffe0; - border-color: #e6db55; - margin: 0 auto; - width: 330px; +.updated, .login #login_error, .login .message { + background-color: #ffffe0; + border-color: #e6db55; + margin: 0 auto; + width: 330px; } #login fieldset { - border: 0; + border: 0; } #login fieldset.actions { - line-height: 35px; - width: 315px; - margin-top: 10px; -} - -#login h1 -{ - text-align: center; - color: #666; - margin: 0 0 30px 0; - font: normal 26px/1 Verdana, Helvetica; - position: relative; -} - -#login -{ - background-color: #fafafa; - width: 360px; - padding: 30px; - margin: 50px auto 0 auto; - z-index: 0; - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - border-radius: 3px; - -webkit-box-shadow: - 0 0 2px rgba(0, 0, 0, 0.2), - 0 1px 1px rgba(0, 0, 0, .2); - -moz-box-shadow: - 0 0 2px rgba(0, 0, 0, 0.2), - 1px 1px 0 rgba(0, 0, 0, .1); - box-shadow: - 0 0 2px rgba(0, 0, 0, 0.2), - 0 1px 1px rgba(0, 0, 0, .2); -} - -#login form { margin: 0 5px; position: relative; } + line-height: 35px; + width: 315px; + margin-top: 10px; +} + +#login h1 { + text-align: center; + color: #666; + margin: 0 0 30px 0; + font: normal 26px/1 Verdana, Helvetica; + position: relative; +} + +#login { + background-color: #fafafa; + width: 360px; + padding: 30px; + margin: 50px auto 0 auto; + z-index: 0; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; + -webkit-box-shadow: 0 0 2px rgba(0, 0, 0, 0.2), 0 1px 1px rgba(0, 0, 0, .2); + -moz-box-shadow: 0 0 2px rgba(0, 0, 0, 0.2), 1px 1px 0 rgba(0, 0, 0, .1); + box-shadow: 0 0 2px rgba(0, 0, 0, 0.2), 0 1px 1px rgba(0, 0, 0, .2); +} + +#login form { + margin: 0 5px; + position: relative; +} + #login form input[type="text"], #login form input[type="password"] { - padding: 10px 15px 10px 45px; - margin: 0 0 15px 0; - width: 253px; /* 258 + 2 + 55 = 315 */ - border: 1px solid #ccc; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - border-radius: 5px; - -moz-box-shadow: 0 1px 1px #ccc inset, 0 1px 0 #fff; - -webkit-box-shadow: 0 1px 1px #ccc inset, 0 1px 0 #fff; - box-shadow: 0 1px 1px #ccc inset, 0 1px 0 #fff; + padding: 10px 15px 10px 45px; + margin: 0 0 15px 0; + width: 253px; /* 258 + 2 + 55 = 315 */ + border: 1px solid #ccc; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius: 5px; + -moz-box-shadow: 0 1px 1px #ccc inset, 0 1px 0 #fff; + -webkit-box-shadow: 0 1px 1px #ccc inset, 0 1px 0 #fff; + box-shadow: 0 1px 1px #ccc inset, 0 1px 0 #fff; } #login_form_rememberme { - vertical-align: middle; + vertical-align: middle; } -#login_error,.message { - margin: 0 0 16px 8px; - border: 1px solid; - padding: 12px; +#login_error, .message { + margin: 0 0 16px 8px; + border: 1px solid; + padding: 12px; } #nav, #piwik { - margin: 0 0 0 8px; - padding: 16px; + margin: 0 0 0 8px; + padding: 16px; } #nav { - text-align: center; + text-align: center; } #nav a:hover { - text-decoration: underline; + text-decoration: underline; } -#login_form_password, #reset_form_password, +#login_form_password, #reset_form_password, #reset_form_password_bis, #login_form_login, #reset_form_login { - background: #fff url(../../../themes/default/images/login-sprite.png) no-repeat; + background: #fff url(../../../themes/default/images/login-sprite.png) no-repeat; } #login_form_password, #reset_form_password, #reset_form_password_bis { - background-position: 10px -51px !important; + background-position: 10px -51px !important; } #login_form_login, #reset_form_login { - background-position: 10px 11px !important; + background-position: 10px 11px !important; } -#login_form_password,#reset_form_password,#reset_form_password_bis, -#login_form_login,#reset_form_login { - font-size: 20px; - width: 97%; - padding: 3px; - margin-right: 6px; +#login_form_password, #reset_form_password, #reset_form_password_bis, +#login_form_login, #reset_form_login { + font-size: 20px; + width: 97%; + padding: 3px; + margin-right: 6px; } #login #login_error { - background-color: #ffebe8; - border-color: #c00; + background-color: #ffebe8; + border-color: #c00; } #login form input.submit { - background-color: #e5e5e5; + background-color: #e5e5e5; } #login form input.submit:hover { - background-color: #eee; + background-color: #eee; } .login #login_error { - background-color: #ffffe0; - border-color: #e6db55; + background-color: #ffffe0; + border-color: #e6db55; } .login #nav a { - color: #777; + color: #777; } + .login #piwik a { - color: #CDCDCD; + color: #CDCDCD; } body.login { - border-top-color: #464646; + border-top-color: #464646; } #login form input { - color: #555; + color: #555; } a { - text-decoration: none; + text-decoration: none; } #logo { - margin: 100px auto 0 auto; - width: 240px; - position: relative; + margin: 100px auto 0 auto; + width: 240px; + position: relative; } #logo .description a { - font:16px/16px 'Patrick Hand'; - color:#666666; - right: auto; - text-decoration: none; + font: 16px/16px 'Patrick Hand'; + color: #666666; + right: auto; + text-decoration: none; } #logo .description { - position: absolute; - left: -40px !important; - top: -30px !important; - -webkit-transform:rotate(-6deg); - -moz-transform:rotate(-6deg); - -ms-transform:rotate(-6deg); - -o-transform:rotate(-6deg); + position: absolute; + left: -40px !important; + top: -30px !important; + -webkit-transform: rotate(-6deg); + -moz-transform: rotate(-6deg); + -ms-transform: rotate(-6deg); + -o-transform: rotate(-6deg); } #logo .description .arrow { - background:url(../../../themes/default/images/affix-arrow.png); - width:50px; - height:68px; - position:absolute; - left:-35px; + background: url(../../../themes/default/images/affix-arrow.png); + width: 50px; + height: 68px; + position: absolute; + left: -35px; } #logo img { - border:0; - vertical-align: bottom; - width: 260px; + border: 0; + vertical-align: bottom; + width: 260px; } #logo .h1 { - font-family: Georgia, "Times New Roman", Times, serif; - font-weight: normal; - color: #136F8B; - font-size: 45pt; - text-transform: none; + font-family: Georgia, "Times New Roman", Times, serif; + font-weight: normal; + color: #136F8B; + font-size: 45pt; + text-transform: none; } .loadingPiwik { - float: left; - margin-left: 16px; + float: left; + margin-left: 16px; } /* IE < 9 will use this */ -html.old-ie .ie-hide { - display: none; +html.old-ie .ie-hide { + display: none; } diff --git a/plugins/Login/templates/login.js b/plugins/Login/templates/login.js index 28171b47ab..5458942fef 100755 --- a/plugins/Login/templates/login.js +++ b/plugins/Login/templates/login.js @@ -4,104 +4,97 @@ * @link http://piwik.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -(function($) { - -$(document).ready(function() { - var switchForm = function(fromFormId, toFormId, message, callback) { - var fromLoginInputId = '#'+fromFormId+'_login', - toLoginInputId = '#'+toFormId+'_login', - toPasswordInputId = '#'+toFormId+'_password', - fromLoginNavId = '#'+fromFormId+'_nav', - toLoginNavId = '#'+toFormId+'_nav'; - - if ($(toLoginInputId).val() === '') - { - $(toLoginInputId).val($(fromLoginInputId).val()); - } - - // hide the bottom portion of the login screen & show the password reset bits - $('#'+fromFormId+',#message_container').fadeOut(500, function() { - // show lost password instructions - $('#message_container').html(message); - - $(fromLoginNavId).hide(); - $(toLoginNavId).show(); - $('#'+toFormId+',#message_container').fadeIn(500, function() { - // focus on login or password control based on whether a login exists - if ($(toLoginInputId).val() === '') - { - $(toLoginInputId).focus(); - } - else - { - $(toPasswordInputId).focus(); - } - - if (callback) - { - callback(); - } - }); - }); - }; - - // 'lost your password?' on click - $('#login_form_nav').click(function(e) { - e.preventDefault(); - switchForm('login_form', 'reset_form', $('#lost_password_instructions').html()); - return false; - }); - - // 'cancel' on click - $('#reset_form_nav,#alternate_reset_nav').click(function(e) { - e.preventDefault(); - $('#alternate_reset_nav').hide(); - switchForm('reset_form', 'login_form', ''); - return false; - }); - - // password reset on submit - $('#reset_form_submit').click(function(e) { - e.preventDefault(); - - var ajaxDone = function(response) - { - $('.loadingPiwik').hide(); - - var isSuccess = response.indexOf('id="login_error"') === -1, - fadeOutIds = '#message_container'; - if (isSuccess) - { - fadeOutIds += ',#reset_form,#reset_form_nav'; - } - - $(fadeOutIds).fadeOut(300, function() { - if (isSuccess) - { - $('#alternate_reset_nav').show(); - } - - $('#message_container').html(response).fadeIn(300); - }); - }; - - $('.loadingPiwik').show(); - - // perform reset password request - $.ajax({ - type: 'POST', - url: 'index.php', - dataType: 'html', - async: true, - error: function() { ajaxDone('
HTTP Error
'); }, - success: ajaxDone, // Callback when the request succeeds - data: $('#reset_form').serialize() - }); - - return false; - }); - - $('#login_form_login').focus(); -}); +(function ($) { + + $(document).ready(function () { + var switchForm = function (fromFormId, toFormId, message, callback) { + var fromLoginInputId = '#' + fromFormId + '_login', + toLoginInputId = '#' + toFormId + '_login', + toPasswordInputId = '#' + toFormId + '_password', + fromLoginNavId = '#' + fromFormId + '_nav', + toLoginNavId = '#' + toFormId + '_nav'; + + if ($(toLoginInputId).val() === '') { + $(toLoginInputId).val($(fromLoginInputId).val()); + } + + // hide the bottom portion of the login screen & show the password reset bits + $('#' + fromFormId + ',#message_container').fadeOut(500, function () { + // show lost password instructions + $('#message_container').html(message); + + $(fromLoginNavId).hide(); + $(toLoginNavId).show(); + $('#' + toFormId + ',#message_container').fadeIn(500, function () { + // focus on login or password control based on whether a login exists + if ($(toLoginInputId).val() === '') { + $(toLoginInputId).focus(); + } + else { + $(toPasswordInputId).focus(); + } + + if (callback) { + callback(); + } + }); + }); + }; + + // 'lost your password?' on click + $('#login_form_nav').click(function (e) { + e.preventDefault(); + switchForm('login_form', 'reset_form', $('#lost_password_instructions').html()); + return false; + }); + + // 'cancel' on click + $('#reset_form_nav,#alternate_reset_nav').click(function (e) { + e.preventDefault(); + $('#alternate_reset_nav').hide(); + switchForm('reset_form', 'login_form', ''); + return false; + }); + + // password reset on submit + $('#reset_form_submit').click(function (e) { + e.preventDefault(); + + var ajaxDone = function (response) { + $('.loadingPiwik').hide(); + + var isSuccess = response.indexOf('id="login_error"') === -1, + fadeOutIds = '#message_container'; + if (isSuccess) { + fadeOutIds += ',#reset_form,#reset_form_nav'; + } + + $(fadeOutIds).fadeOut(300, function () { + if (isSuccess) { + $('#alternate_reset_nav').show(); + } + + $('#message_container').html(response).fadeIn(300); + }); + }; + + $('.loadingPiwik').show(); + + // perform reset password request + $.ajax({ + type: 'POST', + url: 'index.php', + dataType: 'html', + async: true, + error: function () { ajaxDone('
HTTP Error
'); }, + success: ajaxDone, // Callback when the request succeeds + data: $('#reset_form').serialize() + }); + + return false; + }); + + $('#login_form_login').focus(); + }); }(jQuery)); diff --git a/plugins/Login/templates/login.tpl b/plugins/Login/templates/login.tpl index 956f8d4bc8..ad85960ec5 100644 --- a/plugins/Login/templates/login.tpl +++ b/plugins/Login/templates/login.tpl @@ -2,84 +2,89 @@
-{* untrusted host warning *} -{if isset($isValidHost) && isset($invalidHostMessage) && !$isValidHost} -
- {'General_Warning'|translate}: {$invalidHostMessage} + {* untrusted host warning *} + {if isset($isValidHost) && isset($invalidHostMessage) && !$isValidHost} +
+ {'General_Warning'|translate}: {$invalidHostMessage} -

{$invalidHostMessageHowToFix} -

{'General_Help'|translate}
+

{$invalidHostMessageHowToFix} +

{'General_Help'|translate}
-
-{else} -
- {if $form_data.errors} -
- {foreach from=$form_data.errors item=data} - {'General_Error'|translate}: {$data}
- {/foreach} -
- {/if} +
+ {else} +
+ {if $form_data.errors} +
+ {foreach from=$form_data.errors item=data} + {'General_Error'|translate} + : {$data} +
+ {/foreach} +
+ {/if} - {if $AccessErrorString} -
{'General_Error'|translate}: {$AccessErrorString}
- {/if} + {if $AccessErrorString} +
{'General_Error'|translate}: {$AccessErrorString}
+ {/if} - {if $infoMessage} -

{$infoMessage}

- {/if} -
+ {if $infoMessage} +

{$infoMessage}

+ {/if} +
+
+

{'Login_LogIn'|translate}

+
+ + + +
- -

{'Login_LogIn'|translate}

-
- - - -
+
+ + + +
+
+ - -
- - -
- - - - - - -{if isset($smarty.capture.poweredByPiwik)} -

- {$smarty.capture.poweredByPiwik} -

-{/if} - - -{/if} + + + + + {if isset($smarty.capture.poweredByPiwik)} +

+ {$smarty.capture.poweredByPiwik} +

+ {/if} + + {/if}
diff --git a/plugins/Login/templates/message.tpl b/plugins/Login/templates/message.tpl index 7b85147d8f..ff2e9d21e3 100755 --- a/plugins/Login/templates/message.tpl +++ b/plugins/Login/templates/message.tpl @@ -1,11 +1,13 @@ {if isset($infoMessage)} -

{$infoMessage}

+

{$infoMessage}

{/if} {if isset($formErrors)} -

- {foreach from=$formErrors item=data} - {'General_Error'|translate}: {$data}
- {/foreach} -

+

+ {foreach from=$formErrors item=data} + {'General_Error'|translate} + : {$data} +
+ {/foreach} +

{/if} -- cgit v1.2.3