g_sto/plugins/rainlab/user/components/Session.php

226 lines
6.0 KiB
PHP

<?php namespace RainLab\User\Components;
use Lang;
use Auth;
use Event;
use Flash;
use Request;
use Redirect;
use Cms\Classes\Page;
use Cms\Classes\ComponentBase;
use RainLab\User\Models\UserGroup;
use SystemException;
/**
* Session component
*
* This will inject the user object to every page and provide the ability for
* the user to sign out. This can also be used to restrict access to pages.
*/
class Session extends ComponentBase
{
const ALLOW_ALL = 'all';
const ALLOW_GUEST = 'guest';
const ALLOW_USER = 'user';
public function componentDetails()
{
return [
'name' => 'rainlab.user::lang.session.session',
'description' => 'rainlab.user::lang.session.session_desc'
];
}
public function defineProperties()
{
return [
'security' => [
'title' => 'rainlab.user::lang.session.security_title',
'description' => 'rainlab.user::lang.session.security_desc',
'type' => 'dropdown',
'default' => 'all',
'options' => [
'all' => 'rainlab.user::lang.session.all',
'user' => 'rainlab.user::lang.session.users',
'guest' => 'rainlab.user::lang.session.guests'
]
],
'allowedUserGroups' => [
'title' => 'rainlab.user::lang.session.allowed_groups_title',
'description' => 'rainlab.user::lang.session.allowed_groups_description',
'placeholder' => '*',
'type' => 'set',
'default' => []
],
'redirect' => [
'title' => 'rainlab.user::lang.session.redirect_title',
'description' => 'rainlab.user::lang.session.redirect_desc',
'type' => 'dropdown',
'default' => ''
]
];
}
/**
* getRedirectOptions
*/
public function getRedirectOptions()
{
return [''=>'- none -'] + Page::sortBy('baseFileName')->lists('baseFileName', 'baseFileName');
}
/**
* getAllowedUserGroupsOptions
*/
public function getAllowedUserGroupsOptions()
{
return UserGroup::lists('name','code');
}
/**
* Component is initialized.
*/
public function init()
{
// Inject security logic pre-AJAX
$this->controller->bindEvent('page.init', function() {
if (Request::ajax() && ($redirect = $this->checkUserSecurityRedirect())) {
return ['X_OCTOBER_REDIRECT' => $redirect->getTargetUrl()];
}
});
}
/**
* Executed when this component is bound to a page or layout.
*/
public function onRun()
{
if ($redirect = $this->checkUserSecurityRedirect()) {
return $redirect;
}
$this->page['user'] = $this->user();
}
/**
* Returns the logged in user, if available, and touches
* the last seen timestamp.
* @return RainLab\User\Models\User
*/
public function user()
{
if (!$user = Auth::getUser()) {
return null;
}
if (!Auth::isImpersonator()) {
$user->touchLastSeen();
}
return $user;
}
/**
* Returns the previously signed in user when impersonating.
*/
public function impersonator()
{
return Auth::getImpersonator();
}
/**
* Log out the user
*
* Usage:
* <a data-request="onLogout">Sign out</a>
*
* With the optional redirect parameter:
* <a data-request="onLogout" data-request-data="redirect: '/good-bye'">Sign out</a>
*
*/
public function onLogout()
{
$user = Auth::getUser();
Auth::logout();
if ($user) {
Event::fire('rainlab.user.logout', [$user]);
}
$url = post('redirect', Request::fullUrl());
Flash::success(Lang::get('rainlab.user::lang.session.logout'));
return Redirect::to($url);
}
/**
* If impersonating, revert back to the previously signed in user.
* @return Redirect
*/
public function onStopImpersonating()
{
if (!Auth::isImpersonator()) {
return $this->onLogout();
}
Auth::stopImpersonate();
$url = post('redirect', Request::fullUrl());
Flash::success(Lang::get('rainlab.user::lang.session.stop_impersonate_success'));
return Redirect::to($url);
}
/**
* checkUserSecurityRedirect will return a redirect if the user cannot access the page.
*/
protected function checkUserSecurityRedirect()
{
// No security layer enabled
if ($this->checkUserSecurity()) {
return;
}
if (!$this->property('redirect')) {
throw new SystemException('Redirect property is empty on Session component.');
}
$redirectUrl = $this->controller->pageUrl($this->property('redirect'));
return Redirect::guest($redirectUrl);
}
/**
* checkUserSecurity checks if the user can access this page based on the security rules.
*/
protected function checkUserSecurity(): bool
{
$allowedGroup = $this->property('security', self::ALLOW_ALL);
$allowedUserGroups = (array) $this->property('allowedUserGroups', []);
$isAuthenticated = Auth::check();
if ($isAuthenticated) {
if ($allowedGroup == self::ALLOW_GUEST) {
return false;
}
if (!empty($allowedUserGroups)) {
$userGroups = Auth::getUser()->groups->lists('code');
if (!count(array_intersect($allowedUserGroups, $userGroups))) {
return false;
}
}
}
else {
if ($allowedGroup == self::ALLOW_USER) {
return false;
}
}
return true;
}
}