Skip to content

Commit

Permalink
Merge branch 'release/3.5.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
rhukster committed Aug 31, 2021
2 parents 8c591fd + 7679f4c commit 88d6fcd
Show file tree
Hide file tree
Showing 10 changed files with 371 additions and 363 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
# v3.5.0
## 08/31/2021

1. [](#new)
* Require **Grav 1.7.19**, **Form 5.1.0** and **Email 3.1.0**
* Added support for adding login pages by `$grav['login']->addPage()`
* Added support for getting all login routes by `$grav['login']->getRoute()`
* Added support for form layouts
* Deprecated methods `LoginPlugin::defaultRedirectAfterLogin()` and `LoginPlugin::defaultRedirectAfterLogout()`
1. [](#improved)
* Speed up `visibility_requires_access` checks by restricting full check to only visible pages
1. [](#bugfix)
* Fixed login pages with redirect breaking the site

# v3.4.4
## 06/16/2021

Expand Down
8 changes: 4 additions & 4 deletions blueprints.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: Login
slug: login
type: plugin
version: 3.4.4
version: 3.5.0
testing: false
description: Enables user authentication and login screen.
icon: sign-in
Expand All @@ -15,9 +15,9 @@ bugs: https://github.com/getgrav/grav-plugin-login/issues
license: MIT

dependencies:
- { name: grav, version: '>=1.6.7' }
- { name: form, version: '>=3.0.0' }
- { name: email, version: '>=3.0.0' }
- { name: grav, version: '>=1.7.19' }
- { name: form, version: '>=5.1.0' }
- { name: email, version: '>=3.1.0' }

form:
validation: loose
Expand Down
42 changes: 21 additions & 21 deletions classes/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ public function taskLogin()
$event = $this->login->login($form, ['rate_limit' => true, 'remember_me' => true, 'twofa' => $twofa], ['return_event' => true]);
$user = $event->getUser();

$login_redirect = LoginPlugin::defaultRedirectAfterLogin();
$login_redirect = $this->login->getRoute('after_login');

if ($user->authenticated) {
if ($user->authorized) {
Expand All @@ -144,15 +144,14 @@ public function taskLogin()
);
} else {
$redirect_to_login = $this->grav['config']->get('plugins.login.redirect_to_login');
$login_route = $this->grav['config']->get('plugins.login.route');
$redirect_route = $redirect_to_login && $login_route ? $login_route : false;
$event->defRedirect($redirect_route ?: $this->grav['uri']->referrer('/'));
$redirect_route = $redirect_to_login ? $this->login->getRoute('login') : null;
$event->defRedirect($redirect_route ?? $this->grav['uri']->referrer('/'));
}
} else {
if ($user->authorized) {
$event->defMessage('PLUGIN_LOGIN.ACCESS_DENIED', 'error');

$event->defRedirect($this->grav['config']->get('plugins.login.route_unauthorized', '/'));
$event->defRedirect($this->login->getRoute('unauthorized') ?? '/');
} else {
$event->defMessage('PLUGIN_LOGIN.LOGIN_FAILED', 'error');
}
Expand Down Expand Up @@ -215,7 +214,7 @@ public function taskTwoFa()

if (!$event->getRedirect()) {
$redirect_to_login = $this->grav['config']->get('plugins.login.route_to_login');
$login_route = $this->grav['config']->get('plugins.login.route');
$login_route = $this->login->getRoute('login');

$event->setRedirect(
$redirect_to_login && $login_route ? $login_route : $this->getCurrentRedirect(),
Expand All @@ -235,7 +234,7 @@ public function taskTwoFa()
$user->authorized = !$event->isDelayed();

if (!$event->getRedirect()) {
$login_redirect = LoginPlugin::defaultRedirectAfterLogin();
$login_redirect = $this->login->getRoute('after_login');

$event->setRedirect(
$this->grav['session']->redirect_after_login ?: $login_redirect ?: $this->grav['uri']->referrer('/'),
Expand Down Expand Up @@ -290,7 +289,7 @@ public function taskTwofa_cancel()

if (!$event->getRedirect()) {
$redirect_to_login = $this->grav['config']->get('plugins.login.route_to_login');
$login_route = $this->grav['config']->get('plugins.login.route');
$login_route = $this->login->getRoute('login');

$event->setRedirect(
$redirect_to_login && $login_route ? $login_route : $this->getCurrentRedirect(),
Expand Down Expand Up @@ -319,7 +318,7 @@ public function taskLogout()
$messages->add($t->translate($message), $event->getMessageType());
}

$logout_redirect = LoginPlugin::defaultRedirectAfterLogout();
$logout_redirect = $this->login->getRoute('after_logout');

$redirect = $event->getRedirect() ?: $logout_redirect ?: $this->getCurrentRedirect();
if ($redirect) {
Expand Down Expand Up @@ -354,30 +353,30 @@ protected function taskForgot()

if (!isset($this->grav['Email'])) {
$messages->add($language->translate('PLUGIN_LOGIN.FORGOT_EMAIL_NOT_CONFIGURED'), 'error');
$this->setRedirect($this->grav['config']->get('plugins.login.route_forgot', '/'));
$this->setRedirect($this->login->getRoute('forgot') ?? '/');

return true;
}

if (!$user || !$user->exists()) {
$messages->add($language->translate('PLUGIN_LOGIN.FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL'), 'info');
$this->setRedirect($this->grav['config']->get('plugins.login.route_forgot', '/'));
$this->setRedirect($this->login->getRoute('forgot') ?? '/');

return true;
}

if (empty($user->email)) {
$messages->add($language->translate(['PLUGIN_LOGIN.FORGOT_CANNOT_RESET_EMAIL_NO_EMAIL', $email]),
'error');
$this->setRedirect($this->grav['config']->get('plugins.login.route_forgot', '/'));
$this->setRedirect($this->login->getRoute('forgot') ?? '/');

return true;
}

if (empty($user->password) && empty($user->hashed_password)) {
$messages->add($language->translate(['PLUGIN_LOGIN.FORGOT_CANNOT_RESET_EMAIL_NO_PASSWORD', $email]),
'error');
$this->setRedirect($this->grav['config']->get('plugins.login.route_forgot', '/'));
$this->setRedirect($this->login->getRoute('forgot') ?? '/');

return true;
}
Expand All @@ -386,7 +385,7 @@ protected function taskForgot()

if (empty($from)) {
$messages->add($language->translate('PLUGIN_LOGIN.FORGOT_EMAIL_NOT_CONFIGURED'), 'error');
$this->setRedirect($this->grav['config']->get('plugins.login.route_forgot', '/'));
$this->setRedirect($this->login->getRoute('forgot') ?? '/');

return true;
}
Expand All @@ -397,7 +396,7 @@ protected function taskForgot()

if ($rateLimiter->isRateLimited($userKey)) {
$messages->add($language->translate(['PLUGIN_LOGIN.FORGOT_CANNOT_RESET_IT_IS_BLOCKED', $email, $rateLimiter->getInterval()]), 'error');
$this->setRedirect($this->grav['config']->get('plugins.login.route', '/'));
$this->setRedirect($this->login->getRoute('login') ?? '/');

return true;
}
Expand All @@ -417,7 +416,8 @@ protected function taskForgot()
$lang = '';
}

$reset_link = $this->grav['base_url_absolute'] . $lang . $this->grav['config']->get('plugins.login.route_reset') . '/task' . $param_sep . 'login.reset/token' . $param_sep . $token . '/user' . $param_sep . $user->username . '/nonce' . $param_sep . Utils::getNonce('reset-form');
$resetRoute = $this->login->getRoute('reset');
$reset_link = $this->grav['base_url_absolute'] . $lang . $resetRoute . '/task' . $param_sep . 'login.reset/token' . $param_sep . $token . '/user' . $param_sep . $user->username . '/nonce' . $param_sep . Utils::getNonce('reset-form');

$sitename = $this->grav['config']->get('site.title', 'Website');

Expand All @@ -434,7 +434,7 @@ protected function taskForgot()
$messages->add($language->translate('PLUGIN_LOGIN.FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL'), 'info');
}

$this->setRedirect($this->grav['config']->get('plugins.login.route', '/'));
$this->setRedirect($this->login->getRoute('login') ?? '/');

return true;
}
Expand Down Expand Up @@ -466,7 +466,7 @@ public function taskReset()
if ($good_token === $token) {
if (time() > $expire) {
$messages->add($language->translate('PLUGIN_LOGIN.RESET_LINK_EXPIRED'), 'error');
$this->grav->redirectLangSafe($this->grav['config']->get('plugins.login.route_forgot', '/'));
$this->grav->redirectLangSafe($this->login->getRoute('forgot') ?? '/');

return true;
}
Expand All @@ -476,14 +476,14 @@ public function taskReset()
$user->save();

$messages->add($language->translate('PLUGIN_LOGIN.RESET_PASSWORD_RESET'), 'info');
$this->setRedirect($this->grav['config']->get('plugins.login.route', '/'));
$this->setRedirect($this->login->getRoute('login') ?? '/');

return true;
}
}

$messages->add($language->translate('PLUGIN_LOGIN.RESET_INVALID_LINK'), 'error');
$this->grav->redirectLangSafe($this->grav['config']->get('plugins.login.route_forgot'));
$this->grav->redirectLangSafe($this->login->getRoute('forgot') ?? '/');

return true;

Expand All @@ -494,7 +494,7 @@ public function taskReset()

if (!$user || !$token) {
$messages->add($language->translate('PLUGIN_LOGIN.RESET_INVALID_LINK'), 'error');
$this->grav->redirectLangSafe($this->grav['config']->get('plugins.login.route_forgot'));
$this->grav->redirectLangSafe($this->login->getRoute('forgot') ?? '/');

return true;
}
Expand Down
102 changes: 99 additions & 3 deletions classes/Login.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
use Grav\Common\Grav;
use Grav\Common\Language\Language;
use Grav\Common\Page\Interfaces\PageInterface;
use Grav\Common\Page\Page;
use Grav\Common\Page\Pages;
use Grav\Common\Session;
use Grav\Common\User\Interfaces\UserCollectionInterface;
use Grav\Common\User\Interfaces\UserInterface;
Expand Down Expand Up @@ -78,9 +80,9 @@ public function __construct(Grav $grav)

/**
* @param string $message
* @param array $data
* @param object|array $data
*/
public static function addDebugMessage(string $message, $data = [])
public static function addDebugMessage(string $message, $data = []): void
{
/** @var Debugger $debugger */
$debugger = Grav::instance()['debugger'];
Expand Down Expand Up @@ -168,6 +170,8 @@ public function logout(array $options = [], $extra = [])
$grav = Grav::instance();

if ($extra instanceof UserInterface) {
user_error(__METHOD__ . '($options, $user) is deprecated since Login Plugin 3.5.0, use logout($options, [\'user\' => $user]) instead', E_USER_DEPRECATED);

$extra = ['user' => $extra];
} elseif (isset($extra['user'])) {
$extra['user'] = $grav['user'];
Expand Down Expand Up @@ -513,7 +517,8 @@ public function sendActivationEmail(UserInterface $user)
$user->save();

$param_sep = $this->config->get('system.param_sep', ':');
$activation_link = $this->grav['base_url_absolute'] . $this->config->get('plugins.login.route_activate') . '/token' . $param_sep . $token . '/username' . $param_sep . $user->username;
$activationRoute = $this->getRoute('activate');
$activation_link = $this->grav['base_url_absolute'] . $activationRoute . '/token' . $param_sep . $token . '/username' . $param_sep . $user->username;

$site_name = $this->config->get('site.title', 'Website');
$author = $this->grav['config']->get('site.author.name', '');
Expand Down Expand Up @@ -622,6 +627,97 @@ public function getRateLimiter($context, $maxCount = null, $interval = null)
return $this->rateLimiters[$context];
}

/**
* Add Login page.
*
* @param string $type
* @param string|null $route Optional route if we want to force-add the page.
* @param PageInterface|null $page
* @return PageInterface|null
*/
public function addPage(string $type, string $route = null, PageInterface $page = null): ?PageInterface
{
$route = $route ?? $this->getRoute($type);
if (null === $route) {
return null;
}

/** @var Pages $pages */
$pages = $this->grav['pages'];

if ($page) {
$route = $route ?? '/login';
$page->route($route);
$page->slug(basename($route));
} else {
$page = $pages->find($route);
}
if (!$page instanceof PageInterface) {
// Only add login page if it hasn't already been defined.
$page = new Page();
$page->init(new \SplFileInfo('plugin://login/pages/' . $type . '.md'));
$page->slug(basename($route));
}

$pages->addPage($page, $route);

// Login page may not have the correct Cache-Control header set, force no-store for the proxies.
$cacheControl = $page->cacheControl();
if (!$cacheControl) {
$page->cacheControl('private, no-cache, must-revalidate');
}

return $page;
}

/**
* Get route to a given login page.
*
* @param string $type Use one of: login, activate, forgot, reset, profile, unauthorized, after_login, after_logout,
* register, after_registration, after_activation
* @return string|null Returns route or null if the route has been disabled.
*/
public function getRoute(string $type): ?string
{
switch ($type) {
case 'login':
$route = $this->config->get('plugins.login.route');
break;
case 'activate':
case 'forgot':
case 'reset':
case 'profile':
$route = $this->config->get('plugins.login.route_' . $type);
break;
case 'unauthorized':
$route = $this->config->get('plugins.login.route_' . $type, '/');
break;
case 'after_login':
case 'after_logout':
$route = $this->config->get('plugins.login.redirect_' . $type);
if ($route === true) {
$route = $this->config->get('plugins.login.route_' . $type);
}
break;
case 'register':
$enabled = $this->config->get('plugins.login.user_registration.enabled', false);
$route = $enabled === true ? $this->config->get('plugins.login.route_' . $type) : null;
break;
case 'after_registration':
case 'after_activation':
$route = $this->config->get('plugins.login.redirect_' . $type);
break;
default:
$route = null;
}

if (!is_string($route) || $route === '') {
return null;
}

return $route;
}

/**
* @param UserInterface $user
* @param PageInterface $page
Expand Down
Loading

0 comments on commit 88d6fcd

Please sign in to comment.