Skip to content

Commit

Permalink
Merge branch 'release/2.4.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
rhukster committed Sep 8, 2017
2 parents 332ae1f + f6a4f2d commit b2dd5fa
Show file tree
Hide file tree
Showing 53 changed files with 2,911 additions and 343 deletions.
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
# v2.4.0
## 09/07/2017

1. [](#new)
* Added the ability to have a custom route for login page, but not redirect
* Added a new `unauthorized.md` page that can be customized as needed
1. [](#improved)
* Differentiated between `authenticated` and `authorized`
* Moved rate-limiting logic to the Login class
* Much code cleanup and removing of cruft
* Updated vendor libraries
* Added Russian translation
1. [](#bugfix)
* Fixed login JSON response in case of login failure
* Fixed issue with profile form displaying on login page
* Store referrer page when trying to access Profile page
* Fixed error when logging out with an expired session

# v2.3.2
## 06/22/2017

Expand Down
4 changes: 2 additions & 2 deletions blueprints.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: Login
version: 2.3.2
version: 2.4.0
description: Enables user authentication and login screen.
icon: sign-in
author:
Expand All @@ -13,7 +13,7 @@ bugs: https://github.com/getgrav/grav-plugin-login/issues
license: MIT

dependencies:
- { name: grav, version: '>=1.2.3' }
- { name: grav, version: '>=1.3.3' }
- { name: form, version: '>=2.4.0' }
- { name: email, version: '~2.0' }

Expand Down
144 changes: 44 additions & 100 deletions classes/Controller.php
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
<?php

/**
* @package Grav.Plugin.Login
*
* @copyright Copyright (C) 2014 - 2017 RocketTheme, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Plugin\Login;

use Birke\Rememberme\Cookie;
use Grav\Common\Config\Config;
use Grav\Common\Grav;
use Grav\Plugin\Login\RememberMe;
use Grav\Common\Language\Language;
use Grav\Common\User\User;
use Grav\Common\Utils;
use Grav\Plugin\Email\Utils as EmailUtils;

use Birke\Rememberme\Cookie;
use RocketTheme\Toolbox\Session\Message;
use Grav\Plugin\Login\RememberMe;

/**
* Class Controller
Expand Down Expand Up @@ -50,7 +53,7 @@ class Controller
protected $prefix = 'task';

/**
* @var \Birke\Rememberme\Authenticator
* @var RememberMe\RememberMe
*/
protected $rememberMe;

Expand All @@ -69,7 +72,7 @@ public function __construct(Grav $grav, $action, $post = null)
$this->grav = $grav;
$this->action = $action;
$this->login = isset($this->grav['login']) ? $this->grav['login'] : '';
$this->post = $this->getPost($post);
$this->post = $post ? $this->getPost($post) : [];

$this->rememberMe();
}
Expand All @@ -95,7 +98,7 @@ public function execute()
try {
$success = call_user_func([$this, $method]);
} catch (\RuntimeException $e) {
$this->setMessage($e->getMessage(), 'error');
$this->login->setMessage($e->getMessage(), 'error');
}

if (!$this->redirect && isset($redirect)) {
Expand All @@ -121,8 +124,8 @@ public function taskLogin()
$count = $this->grav['config']->get('plugins.login.max_login_count', 5);
$interval =$this->grav['config']->get('plugins.login.max_login_interval', 10);

if ($this->isUserRateLimited($user, 'login_attempts', $count, $interval)) {
$this->setMessage($t->translate(['PLUGIN_LOGIN.TOO_MANY_LOGIN_ATTEMPTS', $interval]), 'error');
if ($this->login->isUserRateLimited($user, 'login_attempts', $count, $interval)) {
$this->login->setMessage($t->translate(['PLUGIN_LOGIN.TOO_MANY_LOGIN_ATTEMPTS', $interval]), 'error');
$this->setRedirect($this->grav['config']->get('plugins.login.route', '/'));

return true;
Expand All @@ -132,7 +135,7 @@ public function taskLogin()
if ($this->authenticate($this->post)) {
$this->login->setMessage($t->translate('PLUGIN_LOGIN.LOGIN_SUCCESSFUL'));

$this->resetRateLimit($user, 'login_attempts');
$this->login->resetRateLimit($user, 'login_attempts');

$redirect = $this->grav['config']->get('plugins.login.redirect_after_login');
if (!$redirect) {
Expand All @@ -141,9 +144,10 @@ public function taskLogin()
$this->setRedirect($redirect);
} else {
if ($user->username) {
$this->setMessage($t->translate('PLUGIN_LOGIN.ACCESS_DENIED'), 'error');
$this->login->setMessage($t->translate('PLUGIN_LOGIN.ACCESS_DENIED'), 'error');
$this->setRedirect($this->grav['config']->get('plugins.login.route_unauthorized', '/'));
} else {
$this->setMessage($t->translate('PLUGIN_LOGIN.LOGIN_FAILED'), 'error');
$this->login->setMessage($t->translate('PLUGIN_LOGIN.LOGIN_FAILED'), 'error');
}
}

Expand Down Expand Up @@ -223,7 +227,7 @@ protected function taskForgot()
$count = $this->grav['config']->get('plugins.login.max_pw_resets_count', 0);
$interval =$this->grav['config']->get('plugins.login.max_pw_resets_interval', 2);

if ($this->isUserRateLimited($user, 'pw_resets', $count, $interval)) {
if ($this->login->isUserRateLimited($user, 'pw_resets', $count, $interval)) {
$messages->add($language->translate(['PLUGIN_LOGIN.FORGOT_CANNOT_RESET_IT_IS_BLOCKED', $email, $interval]), 'error');
$this->setRedirect($this->grav['config']->get('plugins.login.route', '/'));

Expand Down Expand Up @@ -278,7 +282,7 @@ public function taskReset()
$password = isset($data['password']) ? $data['password'] : null;
$token = isset($data['token']) ? $data['token'] : null;

if (!empty($user) && $user->exists() && !empty($user->reset)) {
if ($user && !empty($user->reset) && $user->exists()) {
list($good_token, $expire) = explode('::', $user->reset);

if ($good_token === $token) {
Expand Down Expand Up @@ -309,16 +313,16 @@ public function taskReset()

return true;

} else {
$user = $this->grav['uri']->param('user');
$token = $this->grav['uri']->param('token');
}

if (empty($user) || empty($token)) {
$messages->add($language->translate('PLUGIN_LOGIN.RESET_INVALID_LINK'), 'error');
$this->grav->redirect($this->grav['config']->get('plugins.login.route_forgot'));
$user = $this->grav['uri']->param('user');
$token = $this->grav['uri']->param('token');

return true;
}
if (!$user || !$token) {
$messages->add($language->translate('PLUGIN_LOGIN.RESET_INVALID_LINK'), 'error');
$this->grav->redirect($this->grav['config']->get('plugins.login.route_forgot'));

return true;
}

return true;
Expand All @@ -341,31 +345,28 @@ protected function authenticate($form)

// Normal login process
$user = User::find($username);
if ($user->exists()) {
if (!empty($form['username']) && !empty($form['password'])) {
// Authenticate user
$user->authenticated = $user->authenticate($form['password']);
if ($user->exists() && !empty($form['username']) && !empty($form['password'])) {
// Authenticate user
$user->authenticated = $user->authenticate($form['password']);

if ($user->authenticated) {
if ($user->authenticated) {

// Authorize against user ACL
$user_authorized = $user->authorize('site.login');
// Authorize against user ACL
$user_authorized = $user->authorize('site.login');

if ($user_authorized) {
$this->grav['session']->user = $user;
if ($user_authorized) {
$this->grav['session']->user = $user;

unset($this->grav['user']);
$this->grav['user'] = $user;
unset($this->grav['user']);
$this->grav['user'] = $user;

// If the user wants to be remembered, create Rememberme cookie
if (!empty($form['rememberme'])) {
$this->rememberMe->createCookie($form['username']);
} else {
$this->rememberMe->clearCookie();
$this->rememberMe->getStorage()->cleanAllTriplets($user->get('username'));
}
// If the user wants to be remembered, create Rememberme cookie
if (!empty($form['rememberme'])) {
$this->rememberMe->createCookie($form['username']);
} else {
$this->rememberMe->clearCookie();
$this->rememberMe->getStorage()->cleanAllTriplets($user->get('username'));
}

}
}
}
Expand Down Expand Up @@ -400,19 +401,6 @@ public function setRedirect($path, $code = 303)
$this->redirectCode = $code;
}

/**
* Add message into the session queue.
*
* @param string $msg
* @param string $type
*/
public function setMessage($msg, $type = 'info')
{
/** @var Message $messages */
$messages = $this->grav['messages'];
$messages->add($msg, $type);
}

/**
* Gets and sets the RememberMe class
*
Expand Down Expand Up @@ -458,7 +446,7 @@ public function rememberMe($var = null)
*
* @return array
*/
protected function &getPost($post)
protected function &getPost(array $post)
{
unset($post[$this->prefix]);

Expand Down Expand Up @@ -491,48 +479,4 @@ protected function jsonDecode(array $data)
return $data;
}


/**
* Check if user may use password reset functionality.
*
* @param User $user
* @param $field
* @param $count
* @param $interval
* @return bool
*/
protected function isUserRateLimited(User $user, $field, $count, $interval)
{
if ($count > 0) {
if (!isset($user->$field)) {
$user->$field = array();
}
//remove older than 1 hour attempts
$actual_resets = array();
foreach ($user->$field as $reset) {
if ($reset > (time() - $interval * 60)) {
$actual_resets[] = $reset;
}
}

if (count($actual_resets) >= $count) {
return true;
}
$actual_resets[] = time(); // current reset
$user->$field = $actual_resets;

}
return false;
}

/**
* Reset the rate limit counter
*
* @param User $user
* @param $field
*/
protected function resetRateLimit(User $user, $field)
{
$user->$field = [];
}
}
Loading

0 comments on commit b2dd5fa

Please sign in to comment.