From 07359d82f60cb3c6dbca20ada093a7ba22e6f2fc Mon Sep 17 00:00:00 2001 From: Dmitry Khomutov Date: Mon, 28 Aug 2017 21:23:27 +0700 Subject: [PATCH] 'Remember me' on login. Issue #81. --- public/index.php | 1 - .../Controller/SessionController.php | 53 ++++++- src/PHPCensor/Languages/lang.en.php | 11 +- src/PHPCensor/Languages/lang.ru.php | 11 +- ...20170828142020_added_remember_me_login.php | 24 ++++ src/PHPCensor/Model/User.php | 39 ++++++ src/PHPCensor/Store/UserStore.php | 34 ++++- src/PHPCensor/View/Settings/index.phtml | 132 ------------------ 8 files changed, 158 insertions(+), 147 deletions(-) create mode 100644 src/PHPCensor/Migrations/20170828142020_added_remember_me_login.php delete mode 100644 src/PHPCensor/View/Settings/index.phtml diff --git a/public/index.php b/public/index.php index 8a846977..38cf5393 100644 --- a/public/index.php +++ b/public/index.php @@ -1,6 +1,5 @@ userStore->getByRememberKey($_COOKIE['remember_key']); + if ($user) { + $_SESSION['php-censor-user-id'] = $user->getId(); + + $response = new b8\Http\Response\RedirectResponse(); + $response->setHeader('Location', $this->getLoginRedirect()); + + return $response; + } + } + $isLoginFailure = false; if ($this->request->getMethod() == 'POST') { @@ -53,10 +65,10 @@ class SessionController extends Controller $email = $this->getParam('email'); $password = $this->getParam('password', ''); + $rememberMe = (bool)$this->getParam('remember_me', 0); $isLoginFailure = true; - $user = $this->userStore->getByEmailOrName($email); - + $user = $this->userStore->getByEmailOrName($email); $providers = $this->authentication->getLoginPasswordProviders(); if (null !== $user) { @@ -67,7 +79,7 @@ class SessionController extends Controller // Ask each providers to provision the user foreach ($providers as $provider) { $user = $provider->provisionUser($email); - if ($user !== null && $provider->verifyPassword($user, $password)) { + if ($user && $provider->verifyPassword($user, $password)) { $this->userStore->save($user); $isLoginFailure = false; break; @@ -77,8 +89,27 @@ class SessionController extends Controller if (!$isLoginFailure) { $_SESSION['php-censor-user-id'] = $user->getId(); + + if ($rememberMe) { + $rememberKey = md5(microtime(true)); + + $user->setRememberKey($rememberKey); + $this->userStore->save($user); + + setcookie( + 'remember_key', + $rememberKey, + (time() + 60 * 60 * 24 * 30), + null, + null, + null, + true + ); + } + $response = new b8\Http\Response\RedirectResponse(); $response->setHeader('Location', $this->getLoginRedirect()); + return $response; } } @@ -102,6 +133,12 @@ class SessionController extends Controller $pwd->setClass('form-control'); $form->addField($pwd); + $remember = b8\Form\Element\Checkbox::create('remember_me', Lang::get('remember_me'), false); + $remember->setContainerClass('form-group'); + $remember->setCheckedValue(1); + $remember->setValue(0); + $form->addField($remember); + $pwd = new b8\Form\Element\Submit(); $pwd->setValue(Lang::get('log_in')); $pwd->setClass('btn-success'); @@ -129,6 +166,16 @@ class SessionController extends Controller session_destroy(); + setcookie( + 'remember_key', + null, + (time() - 1), + null, + null, + null, + true + ); + $response = new b8\Http\Response\RedirectResponse(); $response->setHeader('Location', APP_URL); return $response; diff --git a/src/PHPCensor/Languages/lang.en.php b/src/PHPCensor/Languages/lang.en.php index 31b229c3..60df69f7 100644 --- a/src/PHPCensor/Languages/lang.en.php +++ b/src/PHPCensor/Languages/lang.en.php @@ -32,11 +32,12 @@ Thank you, PHP Censor', 'reset_email_title' => 'PHP Censor Password Reset for %s', - 'reset_invalid' => 'Invalid password reset request.', - 'email_address' => 'Email Address', - 'login' => 'Login / Email Address', - 'password' => 'Password', - 'log_in' => 'Log in', + 'reset_invalid' => 'Invalid password reset request.', + 'email_address' => 'Email Address', + 'login' => 'Login / Email Address', + 'password' => 'Password', + 'remember_me' => 'Remember me', + 'log_in' => 'Log in', // Top Nav diff --git a/src/PHPCensor/Languages/lang.ru.php b/src/PHPCensor/Languages/lang.ru.php index 8a06099e..3a97b132 100644 --- a/src/PHPCensor/Languages/lang.ru.php +++ b/src/PHPCensor/Languages/lang.ru.php @@ -31,11 +31,12 @@ return [ PHP Censor', 'reset_email_title' => 'Сброс пароля PHP Censor для %s', - 'reset_invalid' => 'Некорректный запрос на сброс пароля.', - 'email_address' => 'Email', - 'login' => 'Логин / Email', - 'password' => 'Пароль', - 'log_in' => 'Войти', + 'reset_invalid' => 'Некорректный запрос на сброс пароля.', + 'email_address' => 'Email', + 'login' => 'Логин / Email', + 'password' => 'Пароль', + 'remember_me' => 'Запомнить меня', + 'log_in' => 'Войти', // Top Nav 'toggle_navigation' => 'Скрыть/показать панель навигации', diff --git a/src/PHPCensor/Migrations/20170828142020_added_remember_me_login.php b/src/PHPCensor/Migrations/20170828142020_added_remember_me_login.php new file mode 100644 index 00000000..0dc4e075 --- /dev/null +++ b/src/PHPCensor/Migrations/20170828142020_added_remember_me_login.php @@ -0,0 +1,24 @@ +table('user'); + + if (!$table->hasColumn('remember_key')) { + $table->addColumn('remember_key', 'string', ['limit' => 32, 'null' => true])->save(); + } + } + + public function down() + { + $table = $this->table('user'); + + if ($table->hasColumn('remember_key')) { + $table->removeColumn('remember_key')->save(); + } + } +} diff --git a/src/PHPCensor/Model/User.php b/src/PHPCensor/Model/User.php index e80582c4..204d81fd 100644 --- a/src/PHPCensor/Model/User.php +++ b/src/PHPCensor/Model/User.php @@ -38,6 +38,7 @@ class User extends Model 'per_page' => null, 'provider_key' => null, 'provider_data' => null, + 'remember_key' => null, ]; /** @@ -54,6 +55,7 @@ class User extends Model 'per_page' => 'getPerPage', 'provider_key' => 'getProviderKey', 'provider_data' => 'getProviderData', + 'remember_key' => 'getRememberKey', // Foreign key getters: ]; @@ -71,6 +73,7 @@ class User extends Model 'per_page' => 'setPerPage', 'provider_key' => 'setProviderKey', 'provider_data' => 'setProviderData', + 'remember_key' => 'setRememberKey', // Foreign key setters: ]; @@ -125,6 +128,12 @@ class User extends Model 'nullable' => true, 'default' => null, ], + 'remember_key' => [ + 'type' => 'varchar', + 'length' => 32, + 'nullable' => true, + 'default' => null, + ], ]; /** @@ -226,6 +235,18 @@ class User extends Model return $rtn; } + /** + * Get the value of RememberKey / remember_key. + * + * @return string + */ + public function getRememberKey() + { + $rtn = $this->data['remember_key']; + + return $rtn; + } + /** * Get the value of Language / language. * @@ -388,6 +409,24 @@ class User extends Model $this->setModified('provider_data'); } + /** + * Set the value of RememberKey / remember_key. + * + * @param $value string + */ + public function setRememberKey($value) + { + $this->validateString('RememberKey', $value); + + if ($this->data['remember_key'] === $value) { + return; + } + + $this->data['remember_key'] = $value; + + $this->setModified('remember_key'); + } + /** * Set the value of Language / language. * diff --git a/src/PHPCensor/Store/UserStore.php b/src/PHPCensor/Store/UserStore.php index dbb356fe..d8f892c9 100644 --- a/src/PHPCensor/Store/UserStore.php +++ b/src/PHPCensor/Store/UserStore.php @@ -94,7 +94,36 @@ class UserStore extends Store } $query = 'SELECT * FROM {{user}} WHERE {{email}} = :value OR {{name}} = :value LIMIT 1'; - $stmt = Database::getConnection()->prepareCommon($query); + $stmt = Database::getConnection()->prepareCommon($query); + $stmt->bindValue(':value', $value); + + if ($stmt->execute()) { + if ($data = $stmt->fetch(\PDO::FETCH_ASSOC)) { + return new User($data); + } + } + + return null; + } + + /** + * + * Get a single User by RememberKey. + * + * @param string $value + * + * @throws HttpException + * + * @return User + */ + public function getByRememberKey($value) + { + if (is_null($value)) { + throw new HttpException('Value passed to ' . __FUNCTION__ . ' cannot be null.'); + } + + $query = 'SELECT * FROM {{user}} WHERE {{remember_key}} = :value LIMIT 1'; + $stmt = Database::getConnection()->prepareCommon($query); $stmt->bindValue(':value', $value); if ($stmt->execute()) { @@ -108,6 +137,9 @@ class UserStore extends Store /** * Get multiple User by Name. + * + * @throws HttpException + * * @return array */ public function getByName($value, $limit = 1000, $useConnection = 'read') diff --git a/src/PHPCensor/View/Settings/index.phtml b/src/PHPCensor/View/Settings/index.phtml deleted file mode 100644 index 68621b27..00000000 --- a/src/PHPCensor/View/Settings/index.phtml +++ /dev/null @@ -1,132 +0,0 @@ - - - -

- -

- - - -

- -

- - - -

- -

- - - -

- -

- - - -

- -

- - -
-
- -
-
- -
-

-
- -
-
- -
-

-
- -
-
- - - -

- -

- -

- - - - - -

- - -
- -
- -
- -
-
-
-

-
- -
-

- -

-
-
-
-
- -
-
- - -
-
-

-
- -
- -

- -

- - - - -
-
- -
-
-

Authentication Settings

-
- -
-

- Be careful: This setting disables authentication and uses your current admin account for all actions within PHP Censor with admin rights. -

- - - -
-