Skip to content

Commit

Permalink
Added $grav->login() and $grav->logout() functions with event hoo…
Browse files Browse the repository at this point in the history
…ks for plugins

Added events `onUserLoginAuthenticate`, `onUserLoginAuthorize`, `onUserLoginFailure`, `onUserLogin`, `onUserLogout`
  • Loading branch information
mahagr committed Aug 8, 2017
1 parent 670f0ce commit 9685ab4
Show file tree
Hide file tree
Showing 6 changed files with 217 additions and 50 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
* Added `Grav\Framework\ContentBlock` classes for nested HTML blocks with CSS/JS assets
* Added `Grav\Framework\Object` classes for creating collections of objects
* Added `Grav\Framework\Page` interfaces
* Deprecated GravTrait
* Added `$grav->login()` and `$grav->logout()` functions with event hooks for plugins
* Added events `onUserLoginAuthenticate`, `onUserLoginAuthorize`, `onUserLoginFailure`, `onUserLogin`, `onUserLogout`
* Added `|nicenumber` Twig filter
* Deprecated GravTrait
1. [](#improved)
* Make it possible to include debug bar also into non-HTML responses

Expand Down
25 changes: 25 additions & 0 deletions system/src/Grav/Common/Grav.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
use Grav\Common\Page\Medium\ImageMedium;
use Grav\Common\Page\Medium\Medium;
use Grav\Common\Page\Page;
use Grav\Common\User\Authentication;
use RocketTheme\Toolbox\DI\Container;
use RocketTheme\Toolbox\Event\Event;
use RocketTheme\Toolbox\Event\EventDispatcher;

class Grav extends Container
{
Expand Down Expand Up @@ -215,6 +217,29 @@ public function redirectLangSafe($route, $code = null)
}
}

public function login(array $credentials, array $options)
{
if (isset($this['user'])) {
return false;
}

$user = Authentication::login($credentials, $options);
if ($user) {
$this['user'] = $user;
}

return $user !== null;
}

public function logout()
{
if (isset($this['user'])) {
Authentication::logout($this['user']);

unset($this['user']);
}
}

/**
* Set response header.
*/
Expand Down
58 changes: 58 additions & 0 deletions system/src/Grav/Common/User/Authentication.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,66 @@

namespace Grav\Common\User;

use Grav\Common\Grav;
use Grav\Common\User\Events\UserLoginEvent;
use RocketTheme\Toolbox\Event\Event;

abstract class Authentication
{
/**
* @param array $credentials
* @param array $options
* @return User|null
*/
public static function login(array $credentials, array $options)
{
$grav = Grav::instance();

$eventOptions = [
'credentials' => $credentials,
'options' => $options
];

$event = new UserLoginEvent($eventOptions);

// Attempt to authenticate the user.
$grav->fireEvent('onUserLoginAuthenticate', $event);

$event->removeCredentials();

// Allow plugins to prevent login after successful authentication.
if ($event['status'] === UserLoginEvent::AUTHENTICATION_SUCCESS) {
$grav->fireEvent('onUserLoginAuthorize', $event);
}

// Allow plugins to log errors or do other tasks on failure.
if ($event['status'] !== UserLoginEvent::AUTHENTICATION_SUCCESS) {
$grav->fireEvent('onUserLoginFailure', $event);

return null;
}

if (empty($event['user']->authenticated)) {
throw new \RuntimeException('Login: User object has not been authenticated!');
}

// User has been logged in, let plugins know.
$grav->fireEvent('onUserLogin', $event);

return $event['user'];
}

public static function logout($user)
{
$grav = Grav::instance();

$event = new Event;
$event->user = $user;

// Logout the user.
$grav->fireEvent('onUserLogout', $event);
}

/**
* Create password hash from plaintext password.
*
Expand Down
77 changes: 77 additions & 0 deletions system/src/Grav/Common/User/Events/UserLoginEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php
/**
* @package Grav.Common.User
*
* @copyright Copyright (C) 2014 - 2017 RocketTheme, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

namespace Grav\Common\User\Events;

use Grav\Common\User\User;
use RocketTheme\Toolbox\Event\Event;

/**
* Class UserLoginEvent
* @package Grav\Common\User\Events
*
* @property int $status
* @property array $credentials
* @property array $options
* @property User $user
* @property string $message
*
*/
class UserLoginEvent extends Event
{
/**
* Undefined event state.
*/
const AUTHENTICATION_UNDEFINED = 0;

/**
* onUserAuthenticate success.
*/
const AUTHENTICATION_SUCCESS = 1;

/**
* onUserAuthenticate fails on bad username/password.
*/
const AUTHENTICATION_FAILURE = 2;

/**
* onUserAuthenticate fails on auth cancellation.
*/
const AUTHENTICATION_CANCELLED = 4;

/**
* onUserAuthorizeLogin fails on expired account.
*/
const AUTHORIZATION_EXPIRED = 8;

/**
* onUserAuthorizeLogin fails for other reasons.
*/
const AUTHORIZATION_DENIED = 16;

public function __construct(array $items = [])
{
$defaults = [
'credentials' => ['username' => '', 'password' => ''],
'options' => ['remember_me' => false],
'status' => static::AUTHENTICATION_UNDEFINED,
'user' => null,
'message' => ''
];

parent::__construct(array_merge_recursive($defaults, $items));

$username = $this['credentials']['username'];
$this['user'] = $username ? User::load($username, false) : new User;
}

public function removeCredentials()
{
unset($this['credentials']);
}
}
60 changes: 31 additions & 29 deletions system/src/Grav/Common/User/Group.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

namespace Grav\Common\User;

use Grav\Common\Config\Config;
use Grav\Common\Data\Blueprints;
use Grav\Common\Data\Data;
use Grav\Common\File\CompiledYamlFile;
Expand All @@ -23,9 +24,7 @@ class Group extends Data
*/
private static function groups()
{
$groups = Grav::instance()['config']->get('groups');

return $groups;
return Grav::instance()['config']->get('groups', []);
}

/**
Expand All @@ -37,7 +36,7 @@ public static function groupNames()
{
$groups = [];

foreach(Grav::instance()['config']->get('groups', []) as $groupname => $group) {
foreach(static::groups() as $groupname => $group) {
$groups[$groupname] = isset($group['readableName']) ? $group['readableName'] : $groupname;
}

Expand Down Expand Up @@ -65,20 +64,15 @@ public static function groupExists($groupname)
*/
public static function load($groupname)
{
if (self::groupExists($groupname)) {
$content = self::groups()[$groupname];
} else {
$content = [];
}
$groups = self::groups();

$content = isset($groups[$groupname]) ? $groups[$groupname] : [];
$content += ['groupname' => $groupname];

$blueprints = new Blueprints;
$blueprint = $blueprints->get('user/group');
if (!isset($content['groupname'])) {
$content['groupname'] = $groupname;
}
$group = new Group($content, $blueprint);

return $group;
return new Group($content, $blueprint);
}

/**
Expand All @@ -87,39 +81,42 @@ public static function load($groupname)
public function save()
{
$grav = Grav::instance();

/** @var Config $config */
$config = $grav['config'];

$blueprints = new Blueprints;
$blueprint = $blueprints->get('user/group');

$fields = $blueprint->fields();

$config->set("groups.$this->groupname", []);
$config->set("groups.{$this->groupname}", []);

$fields = $blueprint->fields();
foreach ($fields as $field) {
if ($field['type'] == 'text') {
if ($field['type'] === 'text') {
$value = $field['name'];
if (isset($this->items['data'][$value])) {
$config->set("groups.$this->groupname.$value", $this->items['data'][$value]);
$config->set("groups.{$this->groupname}.{$value}", $this->items['data'][$value]);
}
}
if ($field['type'] == 'array' || $field['type'] == 'permissions') {
if ($field['type'] === 'array' || $field['type'] === 'permissions') {
$value = $field['name'];
$arrayValues = Utils::getDotNotation($this->items['data'], $field['name']);

if ($arrayValues) {
foreach ($arrayValues as $arrayIndex => $arrayValue) {
$config->set("groups.$this->groupname.$value.$arrayIndex", $arrayValue);
$config->set("groups.{$this->groupname}.{$value}.{$arrayIndex}", $arrayValue);
}
}
}
}

$type = 'groups';
$blueprints = $this->blueprints("config/{$type}");

$filename = CompiledYamlFile::instance($grav['locator']->findResource("config://{$type}.yaml"));

$obj = new Data($config->get($type), $blueprints);
$file = CompiledYamlFile::instance($grav['locator']->findResource("config://{$type}.yaml"));
$obj->file($file);
$obj->file($filename);
$obj->save();
}

Expand All @@ -133,18 +130,23 @@ public function save()
public static function remove($groupname)
{
$grav = Grav::instance();

/** @var Config $config */
$config = $grav['config'];

$blueprints = new Blueprints;
$blueprint = $blueprints->get('user/group');

$groups = $config->get("groups");
$type = 'groups';

$groups = $config->get($type);
unset($groups[$groupname]);
$config->set("groups", $groups);
$config->set($type, $groups);

$type = 'groups';
$obj = new Data($config->get($type), $blueprint);
$file = CompiledYamlFile::instance($grav['locator']->findResource("config://{$type}.yaml"));
$obj->file($file);
$filename = CompiledYamlFile::instance($grav['locator']->findResource("config://{$type}.yaml"));

$obj = new Data($groups, $blueprint);
$obj->file($filename);
$obj->save();

return true;
Expand Down
Loading

0 comments on commit 9685ab4

Please sign in to comment.