mirror of
https://github.com/getgrav/grav-plugin-admin.git
synced 2025-11-03 03:46:30 +01:00
Admin login now uses login plugin events (with option admin: true)
This commit is contained in:
@@ -2,9 +2,10 @@
|
|||||||
## mm/dd/2018
|
## mm/dd/2018
|
||||||
|
|
||||||
1. [](#new)
|
1. [](#new)
|
||||||
* Updated plugin dependencies (Form >=2.13.0, Login >=2.7.0, Email >=2.7.0)
|
* Updated plugin dependencies (Grav >= 1.4.5, Form >=2.13.0, Login >=2.7.0, Email >=2.7.0)
|
||||||
* Updated `pagemedia` form field so it can be used with non-Page objects
|
* Updated `pagemedia` form field so it can be used with non-Page objects
|
||||||
* Moved 2FA authentication to login plugin
|
* Moved 2FA authentication to login plugin
|
||||||
|
* Admin login now uses login plugin events (with option `admin: true`)
|
||||||
1. [](#bugfix)
|
1. [](#bugfix)
|
||||||
* Fixed Firefox issue with the Regenerate button for 2FA. Forcing the page to reload
|
* Fixed Firefox issue with the Regenerate button for 2FA. Forcing the page to reload
|
||||||
* Fixed jumpiness behavior for Regenerate button when on active state.
|
* Fixed jumpiness behavior for Regenerate button when on active state.
|
||||||
|
|||||||
32
admin.php
32
admin.php
@@ -16,6 +16,7 @@ use Grav\Plugin\Admin\Popularity;
|
|||||||
use Grav\Plugin\Admin\Themes;
|
use Grav\Plugin\Admin\Themes;
|
||||||
use Grav\Plugin\Admin\AdminController;
|
use Grav\Plugin\Admin\AdminController;
|
||||||
use Grav\Plugin\Admin\Twig\AdminTwigExtension;
|
use Grav\Plugin\Admin\Twig\AdminTwigExtension;
|
||||||
|
use Grav\Plugin\Form\Form;
|
||||||
use Grav\Plugin\Login\Login;
|
use Grav\Plugin\Login\Login;
|
||||||
use RocketTheme\Toolbox\Event\Event;
|
use RocketTheme\Toolbox\Event\Event;
|
||||||
use RocketTheme\Toolbox\Session\Session;
|
use RocketTheme\Toolbox\Session\Session;
|
||||||
@@ -177,7 +178,6 @@ class AdminPlugin extends Plugin
|
|||||||
* Process the admin registration form.
|
* Process the admin registration form.
|
||||||
*
|
*
|
||||||
* @param Event $event
|
* @param Event $event
|
||||||
* @FIXME: login
|
|
||||||
*/
|
*/
|
||||||
public function onFormProcessed(Event $event)
|
public function onFormProcessed(Event $event)
|
||||||
{
|
{
|
||||||
@@ -266,19 +266,8 @@ class AdminPlugin extends Plugin
|
|||||||
{
|
{
|
||||||
// Only activate admin if we're inside the admin path.
|
// Only activate admin if we're inside the admin path.
|
||||||
if ($this->active) {
|
if ($this->active) {
|
||||||
// Store this version and prefer newer method
|
// Store this version.
|
||||||
if (method_exists($this, 'getBlueprint')) {
|
$this->version = $this->getBlueprint()->version;
|
||||||
$this->version = $this->getBlueprint()->version;
|
|
||||||
} else {
|
|
||||||
$this->version = $this->grav['plugins']->get('admin')->blueprints()->version;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test for correct Grav 1.1 version
|
|
||||||
if (version_compare(GRAV_VERSION, '1.1.0-beta.1', '<')) {
|
|
||||||
$messages = $this->grav['messages'];
|
|
||||||
$messages->add($this->grav['language']->translate(['PLUGIN_ADMIN.NEEDS_GRAV_1_1', GRAV_VERSION]),
|
|
||||||
'error');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Have a unique Admin-only Cache key
|
// Have a unique Admin-only Cache key
|
||||||
if (method_exists($this->grav['cache'], 'setKey')) {
|
if (method_exists($this->grav['cache'], 'setKey')) {
|
||||||
@@ -487,10 +476,19 @@ class AdminPlugin extends Plugin
|
|||||||
|
|
||||||
// add form if it exists in the page
|
// add form if it exists in the page
|
||||||
$header = $page->header();
|
$header = $page->header();
|
||||||
if (isset($header->form)) {
|
|
||||||
// preserve form validation
|
$forms = [];
|
||||||
if (!isset($twig->twig_vars['form'])) {
|
if (isset($header->forms)) foreach ($header->forms as $key => $form) {
|
||||||
|
$forms[$key] = new Form($page, null, $form);
|
||||||
|
}
|
||||||
|
$twig->twig_vars['forms'] = $forms;
|
||||||
|
|
||||||
|
// preserve form validation
|
||||||
|
if (!isset($twig->twig_vars['form'])) {
|
||||||
|
if (isset($header->form)) {
|
||||||
$twig->twig_vars['form'] = new Form($page);
|
$twig->twig_vars['form'] = new Form($page);
|
||||||
|
} elseif (isset($header->forms)) {
|
||||||
|
$twig->twig_vars['form'] = new Form($page, null, reset($header->forms));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ docs: https://github.com/getgrav/grav-plugin-admin/blob/develop/README.md
|
|||||||
license: MIT
|
license: MIT
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
- { name: grav, version: '>=1.4.0' }
|
- { name: grav, version: '>=1.4.5' }
|
||||||
- { name: form, version: '>=2.13.0' }
|
- { name: form, version: '>=2.13.0' }
|
||||||
- { name: login, version: '>=2.7.0' }
|
- { name: login, version: '>=2.7.0' }
|
||||||
- { name: email, version: '>=2.7.0' }
|
- { name: email, version: '>=2.7.0' }
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ use Grav\Common\Uri;
|
|||||||
use Grav\Common\User\User;
|
use Grav\Common\User\User;
|
||||||
use Grav\Common\Utils;
|
use Grav\Common\Utils;
|
||||||
use Grav\Plugin\Admin\Twig\AdminTwigExtension;
|
use Grav\Plugin\Admin\Twig\AdminTwigExtension;
|
||||||
use Grav\Plugin\Admin\Utils as AdminUtils;
|
use Grav\Plugin\Login\Login;
|
||||||
|
use Grav\Plugin\Login\TwoFactorAuth\TwoFactorAuth;
|
||||||
use RocketTheme\Toolbox\Event\Event;
|
use RocketTheme\Toolbox\Event\Event;
|
||||||
use RocketTheme\Toolbox\File\File;
|
use RocketTheme\Toolbox\File\File;
|
||||||
use RocketTheme\Toolbox\File\JsonFile;
|
use RocketTheme\Toolbox\File\JsonFile;
|
||||||
@@ -349,83 +350,126 @@ class Admin
|
|||||||
/**
|
/**
|
||||||
* Authenticate user.
|
* Authenticate user.
|
||||||
*
|
*
|
||||||
* @param array $data Form data.
|
* @param array $credentials User credentials.
|
||||||
* @param array $post Additional form fields.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
* @TODO LOGIN
|
|
||||||
*/
|
*/
|
||||||
public function authenticate($data, $post)
|
public function authenticate($credentials, $post)
|
||||||
{
|
{
|
||||||
$count = $this->grav['config']->get('plugins.login.max_login_count', 5);
|
/** @var Login $login */
|
||||||
$interval = $this->grav['config']->get('plugins.login.max_login_interval', 10);
|
|
||||||
$login = $this->grav['login'];
|
$login = $this->grav['login'];
|
||||||
|
|
||||||
if ($login->isUserRateLimited($this->user, 'login_attempts', $count, $interval)) {
|
// Remove login nonce from the form.
|
||||||
$this->setMessage($this->translate(['PLUGIN_LOGIN.TOO_MANY_LOGIN_ATTEMPTS', $interval]), 'error');
|
$credentials = array_diff_key($credentials, ['admin-nonce' => true]);
|
||||||
$this->grav->redirect($post['redirect']);
|
$twofa = $this->grav['config']->get('plugins.admin.twofa_enabled', false);
|
||||||
return true;
|
|
||||||
|
$rateLimiter = $login->getRateLimiter('login_attempts');
|
||||||
|
|
||||||
|
$userKey = isset($credentials['username']) ? (string)$credentials['username'] : '';
|
||||||
|
$ipKey = Uri::ip();
|
||||||
|
$redirect = isset($post['redirect']) ? $post['redirect'] : $this->uri->route();
|
||||||
|
|
||||||
|
// Check if the current IP has been used in failed login attempts.
|
||||||
|
$attempts = count($rateLimiter->getAttempts($ipKey, 'ip'));
|
||||||
|
|
||||||
|
$rateLimiter->registerRateLimitedAction($ipKey, 'ip')->registerRateLimitedAction($userKey);
|
||||||
|
|
||||||
|
// Check rate limit for both IP and user, but allow each IP a single try even if user is already rate limited.
|
||||||
|
if ($rateLimiter->isRateLimited($ipKey, 'ip') || ($attempts && $rateLimiter->isRateLimited($userKey))) {
|
||||||
|
$this->setMessage($this->translate(['PLUGIN_LOGIN.TOO_MANY_LOGIN_ATTEMPTS', $rateLimiter->getInterval()]), 'error');
|
||||||
|
|
||||||
|
$this->grav->redirect('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fire Login process.
|
||||||
|
$event = $login->login(
|
||||||
|
$credentials,
|
||||||
|
['admin' => true, 'twofa' => $twofa],
|
||||||
|
['authorize' => 'admin.login', 'return_event' => true]
|
||||||
|
);
|
||||||
|
$user = $event->getUser();
|
||||||
|
|
||||||
|
if ($user->authenticated) {
|
||||||
|
$rateLimiter->resetRateLimit($ipKey, 'ip')->resetRateLimit($userKey);
|
||||||
|
if ($user->authorized) {
|
||||||
|
$event->defMessage('PLUGIN_ADMIN.LOGIN_LOGGED_IN', 'info');
|
||||||
|
|
||||||
if (!$this->user->authenticated && isset($data['username'], $data['password'])) {
|
$event->defRedirect($redirect);
|
||||||
// Perform RegEX check on submitted username to check for emails
|
|
||||||
if (filter_var($data['username'], FILTER_VALIDATE_EMAIL)) {
|
|
||||||
$user = AdminUtils::findUserByEmail($data['username']);
|
|
||||||
} else {
|
} else {
|
||||||
$user = User::load($data['username']);
|
$this->session->redirect = $redirect;
|
||||||
|
|
||||||
|
$event->defRedirect($this->uri->route());
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
//default to english if language not set
|
if ($user->authorized) {
|
||||||
if (empty($user->language)) {
|
$event->defMessage('PLUGIN_LOGIN.ACCESS_DENIED', 'error');
|
||||||
$user->set('language', 'en');
|
} else {
|
||||||
}
|
$event->defMessage('PLUGIN_LOGIN.LOGIN_FAILED', 'error');
|
||||||
|
|
||||||
if ($user->exists()) {
|
|
||||||
|
|
||||||
// Authenticate user.
|
|
||||||
$result = $user->authenticate($data['password']);
|
|
||||||
|
|
||||||
if (!$result) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$event->defRedirect($this->uri->route());
|
||||||
|
|
||||||
$twofa_admin_enabled = $this->grav['config']->get('plugins.admin.twofa_enabled', false);
|
$message = $event->getMessage();
|
||||||
if ($twofa_admin_enabled && isset($user->twofa_enabled) &&
|
if ($message) {
|
||||||
$user->twofa_enabled == true && !$user->authenticated) {
|
$this->setMessage($this->translate($message), $event->getMessageType());
|
||||||
$this->session->redirect = $post['redirect'];
|
|
||||||
$this->session->user = $user;
|
|
||||||
|
|
||||||
$this->grav->redirect($this->base . '/twofa');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$user->authenticated = true;
|
$redirect = $event->getRedirect();
|
||||||
$login->resetRateLimit($user,'login_attempts');
|
|
||||||
|
|
||||||
if ($user->authorize('admin.login')) {
|
$this->grav->redirect($redirect, $event->getRedirectCode());
|
||||||
$this->user = $this->session->user = $user;
|
}
|
||||||
|
|
||||||
/** @var Grav $grav */
|
/**
|
||||||
$grav = $this->grav;
|
* Check Two-Factor Authentication.
|
||||||
|
*/
|
||||||
|
public function twoFa($data, $post)
|
||||||
|
{
|
||||||
|
/** @var Login $login */
|
||||||
|
$login = $this->grav['login'];
|
||||||
|
|
||||||
unset($this->grav['user']);
|
/** @var TwoFactorAuth $twoFa */
|
||||||
$this->grav['user'] = $user;
|
$twoFa = $login->twoFactorAuth();
|
||||||
|
$user = $this->grav['user'];
|
||||||
|
|
||||||
$this->setMessage($this->translate('PLUGIN_ADMIN.LOGIN_LOGGED_IN'), 'info');
|
$code = isset($data['2fa_code']) ? $data['2fa_code'] : null;
|
||||||
$grav->redirect($post['redirect']);
|
|
||||||
|
|
||||||
return true; //never reached
|
$secret = isset($user->twofa_secret) ? $user->twofa_secret : null;
|
||||||
|
|
||||||
|
if (!$code || !$secret || !$twoFa->verifyCode($secret, $code)) {
|
||||||
|
$login->logout(['admin' => true]);
|
||||||
|
|
||||||
|
$this->grav['session']->setFlashCookieObject(Admin::TMP_COOKIE_NAME, ['message' => $this->translate('PLUGIN_ADMIN.2FA_FAILED'), 'status' => 'error']);
|
||||||
|
|
||||||
|
$this->grav->redirect($this->uri->route(), 303);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
$this->setMessage($this->translate('PLUGIN_ADMIN.LOGIN_LOGGED_IN'), 'info');
|
||||||
|
|
||||||
|
$user->authorized = true;
|
||||||
|
|
||||||
|
$this->grav->redirect($post['redirect']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logout from admin.
|
||||||
|
*/
|
||||||
|
public function Logout($data, $post)
|
||||||
|
{
|
||||||
|
/** @var Login $login */
|
||||||
|
$login = $this->grav['login'];
|
||||||
|
|
||||||
|
$event = $login->logout(['admin' => true], ['return_event' => true]);
|
||||||
|
|
||||||
|
$event->defMessage('PLUGIN_ADMIN.LOGGED_OUT', 'info');
|
||||||
|
$message = $event->getMessage();
|
||||||
|
if ($message) {
|
||||||
|
$this->grav['session']->setFlashCookieObject(Admin::TMP_COOKIE_NAME, ['message' => $this->translate($message), 'status' => $event->getMessageType()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->grav->redirect($this->base);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool
|
* @return bool
|
||||||
* @todo LOGIN
|
|
||||||
*/
|
*/
|
||||||
public static function doAnyUsersExist()
|
public static function doAnyUsersExist()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -124,41 +124,32 @@ class AdminController extends AdminBaseController
|
|||||||
* Handle login.
|
* Handle login.
|
||||||
*
|
*
|
||||||
* @return bool True if the action was performed.
|
* @return bool True if the action was performed.
|
||||||
* @todo LOGIN
|
|
||||||
*/
|
*/
|
||||||
protected function taskLogin()
|
protected function taskLogin()
|
||||||
{
|
{
|
||||||
$this->data['username'] = strip_tags(strtolower($this->data['username']));
|
$this->admin->authenticate($this->data, $this->post);
|
||||||
if ($this->admin->authenticate($this->data, $this->post)) {
|
|
||||||
// should never reach here, redirects first
|
|
||||||
} else {
|
|
||||||
$this->admin->setMessage($this->admin->translate('PLUGIN_ADMIN.LOGIN_FAILED'), 'error');
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool
|
* @return bool True if the action was performed.
|
||||||
* @todo LOGIN
|
|
||||||
*/
|
*/
|
||||||
protected function task2faverify()
|
protected function taskTwofa()
|
||||||
{
|
{
|
||||||
/** @var TwoFactorAuth $twoFa */
|
$this->admin->twoFa($this->data, $this->post);
|
||||||
$twoFa = $this->grav['login']->twoFactorAuth();
|
|
||||||
$user = $this->grav['user'];
|
|
||||||
|
|
||||||
$secret = isset($user->twofa_secret) ? $user->twofa_secret : null;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(isset($this->data['2fa_code']) && $secret && $twoFa->verifyCode($secret, $this->data['2fa_code']))) {
|
/**
|
||||||
$this->admin->setMessage($this->admin->translate('PLUGIN_ADMIN.2FA_FAILED'), 'error');
|
* Handle logout.
|
||||||
return true;
|
*
|
||||||
}
|
* @return bool True if the action was performed.
|
||||||
|
*/
|
||||||
$this->admin->setMessage($this->admin->translate('PLUGIN_ADMIN.LOGIN_LOGGED_IN'), 'info');
|
protected function taskLogout()
|
||||||
|
{
|
||||||
$user->authenticated = true;
|
$this->admin->logout($this->data, $this->post);
|
||||||
$this->grav->redirect($this->post['redirect']);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -166,7 +157,6 @@ class AdminController extends AdminBaseController
|
|||||||
/**
|
/**
|
||||||
* @param null $secret
|
* @param null $secret
|
||||||
* @return bool
|
* @return bool
|
||||||
* @todo LOGIN
|
|
||||||
*/
|
*/
|
||||||
public function taskRegenerate2FASecret()
|
public function taskRegenerate2FASecret()
|
||||||
{
|
{
|
||||||
@@ -204,29 +194,10 @@ class AdminController extends AdminBaseController
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle logout.
|
|
||||||
*
|
|
||||||
* @return bool True if the action was performed.
|
|
||||||
* @todo LOGIN
|
|
||||||
*/
|
|
||||||
protected function taskLogout()
|
|
||||||
{
|
|
||||||
$message = $this->admin->translate('PLUGIN_ADMIN.LOGGED_OUT');
|
|
||||||
|
|
||||||
$this->admin->session()->invalidate()->start();
|
|
||||||
$this->grav['session']->setFlashCookieObject(Admin::TMP_COOKIE_NAME, ['message' => $message, 'status' => 'info']);
|
|
||||||
|
|
||||||
$this->setRedirect('/');
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle the reset password action.
|
* Handle the reset password action.
|
||||||
*
|
*
|
||||||
* @return bool True if the action was performed.
|
* @return bool True if the action was performed.
|
||||||
* @todo LOGIN
|
|
||||||
*/
|
*/
|
||||||
public function taskReset()
|
public function taskReset()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -546,7 +546,6 @@ PLUGIN_ADMIN:
|
|||||||
FRONTMATTER_IGNORE_FIELDS: "Ignore frontmatter fields"
|
FRONTMATTER_IGNORE_FIELDS: "Ignore frontmatter fields"
|
||||||
FRONTMATTER_IGNORE_FIELDS_HELP: "Certain frontmatter fields may contain Twig but should not be processed, such as 'forms'"
|
FRONTMATTER_IGNORE_FIELDS_HELP: "Certain frontmatter fields may contain Twig but should not be processed, such as 'forms'"
|
||||||
PACKAGE_X_INSTALLED_SUCCESSFULLY: "Package %s installed successfully"
|
PACKAGE_X_INSTALLED_SUCCESSFULLY: "Package %s installed successfully"
|
||||||
NEEDS_GRAV_1_1: "<i class=\"fa fa-exclamation-triangle\"></i> <strong>You are running Grav v%s</strong>. You must update to the latest <strong>Grav v1.1.x</strong> release in order to ensure compatibility. This may require switching to <strong>Testing GPM releases</strong> in the System configuration."
|
|
||||||
ORDERING_DISABLED_BECAUSE_PARENT_SETTING_ORDER: "Parent setting order, ordering disabled"
|
ORDERING_DISABLED_BECAUSE_PARENT_SETTING_ORDER: "Parent setting order, ordering disabled"
|
||||||
ORDERING_DISABLED_BECAUSE_PAGE_NOT_VISIBLE: "Page is not visible, ordering disabled"
|
ORDERING_DISABLED_BECAUSE_PAGE_NOT_VISIBLE: "Page is not visible, ordering disabled"
|
||||||
ORDERING_DISABLED_BECAUSE_TOO_MANY_SIBLINGS: "Ordering via the admin is unsupported because there are more than 200 siblings"
|
ORDERING_DISABLED_BECAUSE_TOO_MANY_SIBLINGS: "Ordering via the admin is unsupported because there are more than 200 siblings"
|
||||||
|
|||||||
@@ -1,22 +1,37 @@
|
|||||||
---
|
---
|
||||||
title: Admin Login
|
title: Admin Login
|
||||||
|
|
||||||
form:
|
forms:
|
||||||
name: login
|
login:
|
||||||
action:
|
action:
|
||||||
method: post
|
method: post
|
||||||
|
|
||||||
fields:
|
fields:
|
||||||
username:
|
username:
|
||||||
type: text
|
type: text
|
||||||
placeholder: PLUGIN_ADMIN.USERNAME_EMAIL
|
placeholder: PLUGIN_ADMIN.USERNAME_EMAIL
|
||||||
autofocus: true
|
autofocus: true
|
||||||
validate:
|
validate:
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
|
password:
|
||||||
|
type: password
|
||||||
|
placeholder: PLUGIN_ADMIN.PASSWORD
|
||||||
|
validate:
|
||||||
|
required: true
|
||||||
|
|
||||||
password:
|
login-twofa:
|
||||||
type: password
|
action:
|
||||||
placeholder: PLUGIN_ADMIN.PASSWORD
|
method: post
|
||||||
validate:
|
|
||||||
required: true
|
fields:
|
||||||
|
2fa_instructions:
|
||||||
|
type: display
|
||||||
|
markdown: true
|
||||||
|
content: PLUGIN_ADMIN.2FA_INSTRUCTIONS
|
||||||
|
2fa_code:
|
||||||
|
type: text
|
||||||
|
id: twofa-code
|
||||||
|
autofocus: true
|
||||||
|
placeholder: PLUGIN_ADMIN.2FA_CODE_INPUT
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
---
|
|
||||||
title: 2-Factor Authentication
|
|
||||||
|
|
||||||
form:
|
|
||||||
fields:
|
|
||||||
2fa_instructions:
|
|
||||||
type: display
|
|
||||||
markdown: true
|
|
||||||
content: PLUGIN_ADMIN.2FA_INSTRUCTIONS
|
|
||||||
2fa_code:
|
|
||||||
type: text
|
|
||||||
autofocus: true
|
|
||||||
placeholder: PLUGIN_ADMIN.2FA_CODE_INPUT
|
|
||||||
---
|
|
||||||
@@ -1,44 +1,11 @@
|
|||||||
{% embed 'partials/login.html.twig' with {title:'Grav Admin Login'} %}
|
{% set user = grav.user %}
|
||||||
|
|
||||||
{% block form %}
|
{% if user.username and user.authenticated %}
|
||||||
|
{% if user.authorized %}
|
||||||
{% if grav.user.username and grav.user.authenticated %}
|
{% include 'partials/login-logout.html.twig' %}
|
||||||
|
{% else %}
|
||||||
<div class="form-actions primary-accent">
|
{% include 'partials/login-twofa.html.twig' %}
|
||||||
<button type="submit" class="button primary" name="task" value="logout"><i class="fa fa-sign-in"></i> {{ 'PLUGIN_ADMIN.LOGOUT'|tu }}</button>
|
{% endif %}
|
||||||
</div>
|
{% else %}
|
||||||
|
{% include 'partials/login-form.html.twig' %}
|
||||||
{% else %}
|
{% endif %}
|
||||||
{% for field in form.fields %}
|
|
||||||
{% if field.type %}
|
|
||||||
<div>
|
|
||||||
{% include ["forms/fields/#{field.type}/#{field.type}.html.twig", 'forms/fields/text/text.html.twig'] %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
<div class="form-actions primary-accent">
|
|
||||||
{% if notAuthorized %}
|
|
||||||
<a class="button secondary" onclick="window.history.back()"><i class="fa fa-reply"></i> {{ 'PLUGIN_ADMIN.BACK'|tu }}</a>
|
|
||||||
<button type="submit" class="button primary" name="task" value="logout"><i class="fa fa-sign-in"></i> {{ 'PLUGIN_ADMIN.LOGOUT'|tu }}</button>
|
|
||||||
{% else %}
|
|
||||||
{% if not authenticated %}
|
|
||||||
<a class="button secondary" href="{{ base_url_relative }}/forgot"><i class="fa fa-exclamation-circle"></i> {{ 'PLUGIN_ADMIN.LOGIN_BTN_FORGOT'|tu }}</a>
|
|
||||||
<button type="submit" class="button primary" name="task" value="login"><i class="fa fa-sign-in"></i> {{ 'PLUGIN_ADMIN.LOGIN_BTN'|tu }}</button>
|
|
||||||
{% else %}
|
|
||||||
<button type="submit" class="button primary" name="task" value="logout"><i class="fa fa-sign-in"></i> {{ 'PLUGIN_ADMIN.LOGOUT'|tu }}</button>
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
$(document).ready( function() {
|
|
||||||
$('#messages').delay(5000).animate({ height: 'toggle', opacity: 'toggle' }, 'slow');
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% endembed %}
|
|
||||||
31
themes/grav/templates/partials/login-form.html.twig
Executable file
31
themes/grav/templates/partials/login-form.html.twig
Executable file
@@ -0,0 +1,31 @@
|
|||||||
|
{% embed 'partials/login.html.twig' with {title: 'Grav Admin Login'} %}
|
||||||
|
|
||||||
|
{% block integration %}
|
||||||
|
|
||||||
|
{# NEW WAY OF INCLUDING 3RD PARTY LOGIN OPTIONS #}
|
||||||
|
{% for template in grav.login.getProviderLoginTemplates %}
|
||||||
|
{% include template %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block form %}
|
||||||
|
{% set form = forms['login'] %}
|
||||||
|
|
||||||
|
{% for field in form.fields %}
|
||||||
|
{% set value = field.name == 'username' ? username : '' %}
|
||||||
|
{% if field.type %}
|
||||||
|
<div>
|
||||||
|
{% include ["forms/fields/#{field.type}/#{field.type}.html.twig", 'forms/fields/text/text.html.twig'] %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
<div class="form-actions primary-accent">
|
||||||
|
<a class="button secondary" href="{{ base_url_relative }}/forgot"><i class="fa fa-exclamation-circle"></i> {{ 'PLUGIN_ADMIN.LOGIN_BTN_FORGOT'|tu }}</a>
|
||||||
|
<button type="submit" class="button primary" name="task" value="login"><i class="fa fa-sign-in"></i> {{ 'PLUGIN_ADMIN.LOGIN_BTN'|tu }}</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% endembed %}
|
||||||
15
themes/grav/templates/partials/login-logout.html.twig
Normal file
15
themes/grav/templates/partials/login-logout.html.twig
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{% embed 'partials/login.html.twig' with {title:'Grav Admin Logout'} %}
|
||||||
|
|
||||||
|
{% block integration %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block form %}
|
||||||
|
|
||||||
|
<div class="form-actions primary-accent">
|
||||||
|
<a class="button secondary" onclick="window.history.back()"><i class="fa fa-reply"></i> {{ 'PLUGIN_ADMIN.BACK'|tu }}</a>
|
||||||
|
<button type="submit" class="button primary" name="task" value="logout"><i class="fa fa-sign-in"></i> {{ 'PLUGIN_ADMIN.LOGOUT'|tu }}</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% endembed %}
|
||||||
26
themes/grav/templates/partials/login-twofa.html.twig
Normal file
26
themes/grav/templates/partials/login-twofa.html.twig
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{% embed 'partials/login.html.twig' with {title:'Grav 2-Factor Authentication', redirect: admin.session.redirect} %}
|
||||||
|
|
||||||
|
{% block integration %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block form %}
|
||||||
|
|
||||||
|
{% set form = forms['login-twofa'] %}
|
||||||
|
|
||||||
|
{% for field in form.fields %}
|
||||||
|
{% if field.type %}
|
||||||
|
<div>
|
||||||
|
{% include ["forms/fields/#{field.type}/#{field.type}.html.twig", 'forms/fields/text/text.html.twig'] %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
<div class="{{ form_button_outer_classes ?: 'form-actions secondary-accent' }}">
|
||||||
|
<div class="form-actionst">
|
||||||
|
<button type="submit" class="button primary" name="task" value="twofa">{{ 'PLUGIN_LOGIN.BTN_LOGIN'|t }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% endembed %}
|
||||||
@@ -13,6 +13,8 @@
|
|||||||
|
|
||||||
{% block instructions %}{% endblock %}
|
{% block instructions %}{% endblock %}
|
||||||
|
|
||||||
|
{% block integration %}{% endblock %}
|
||||||
|
|
||||||
{% set redirect = redirect ?: uri.route(false) %}
|
{% set redirect = redirect ?: uri.route(false) %}
|
||||||
|
|
||||||
<form method="post" action="{{ base_url_relative }}">
|
<form method="post" action="{{ base_url_relative }}">
|
||||||
@@ -22,6 +24,12 @@
|
|||||||
{{ nonce_field('admin-form', 'admin-nonce')|raw }}
|
{{ nonce_field('admin-form', 'admin-nonce')|raw }}
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(document).ready( function() {
|
||||||
|
$('#messages').delay(5000).animate({ height: 'toggle', opacity: 'toggle' }, 'slow');
|
||||||
|
});
|
||||||
|
</script>
|
||||||
</section>
|
</section>
|
||||||
</body>
|
</body>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
{% embed 'partials/login.html.twig' with {title:'Grav 2-Factor Authentication', redirect: admin.session.redirect} %}
|
|
||||||
|
|
||||||
{% block form %}
|
|
||||||
{% for field in form.fields %}
|
|
||||||
{% if field.type %}
|
|
||||||
<div>
|
|
||||||
{% include ["forms/fields/#{field.type}/#{field.type}.html.twig", 'forms/fields/text/text.html.twig'] %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
<div class="form-actions primary-accent">
|
|
||||||
<button type="submit" class="button primary" name="task" value="2faverify"><i class="fa fa-sign-in"></i> {{ 'PLUGIN_ADMIN.LOGIN_BTN'|tu }}</button>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% endembed %}
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user