re #22 added impersonation

This commit is contained in:
Antonio Ramirez
2017-07-18 23:47:23 +02:00
parent 2301ccfe45
commit d3b4161f7c
6 changed files with 122 additions and 5 deletions

View File

@ -100,6 +100,7 @@ class Bootstrap implements BootstrapInterface
$di->set(Service\UserConfirmationService::class); $di->set(Service\UserConfirmationService::class);
$di->set(Service\AuthItemEditionService::class); $di->set(Service\AuthItemEditionService::class);
$di->set(Service\UpdateAuthAssignmentsService::class); $di->set(Service\UpdateAuthAssignmentsService::class);
$di->set(Service\SwitchIdentityService::class);
// email change strategy // email change strategy
$di->set(Strategy\DefaultEmailChangeStrategy::class); $di->set(Strategy\DefaultEmailChangeStrategy::class);

View File

@ -18,6 +18,7 @@ use Da\User\Model\Profile;
use Da\User\Model\User; use Da\User\Model\User;
use Da\User\Query\UserQuery; use Da\User\Query\UserQuery;
use Da\User\Search\UserSearch; use Da\User\Search\UserSearch;
use Da\User\Service\SwitchIdentityService;
use Da\User\Service\UserBlockService; use Da\User\Service\UserBlockService;
use Da\User\Service\UserConfirmationService; use Da\User\Service\UserConfirmationService;
use Da\User\Service\UserCreateService; use Da\User\Service\UserCreateService;
@ -80,6 +81,7 @@ class AdminController extends Controller
'delete' => ['post'], 'delete' => ['post'],
'confirm' => ['post'], 'confirm' => ['post'],
'block' => ['post'], 'block' => ['post'],
'switch-identity' => ['post']
], ],
], ],
'access' => [ 'access' => [
@ -287,4 +289,19 @@ class AdminController extends Controller
return $this->redirect(Url::previous('actions-redirect')); return $this->redirect(Url::previous('actions-redirect'));
} }
public function actionSwitchIdentity($id = null)
{
/** @var \Da\User\Module $module */
$module = $this->module;
if (false === $module->enableSwitchIdentities) {
Yii::$app->getSession()->setFlash('danger', Yii::t('usuario', 'Switch identities is disabled.'));
return $this->redirect(['index']);
}
$this->make(SwitchIdentityService::class, [$this, 'userId' => $id])->run();
return $this->goHome();
}
} }

View File

@ -34,6 +34,8 @@ class UserEvent extends Event
const EVENT_AFTER_BLOCK = 'afterBlock'; const EVENT_AFTER_BLOCK = 'afterBlock';
const EVENT_BEFORE_LOGOUT = 'beforeLogout'; const EVENT_BEFORE_LOGOUT = 'beforeLogout';
const EVENT_AFTER_LOGOUT = 'afterLogout'; const EVENT_AFTER_LOGOUT = 'afterLogout';
const EVENT_BEFORE_SWITCH_IDENTITY = 'beforeSwitchIdentity';
const EVENT_AFTER_SWITCH_IDENTITY = 'afterSwitchIdentity';
protected $user; protected $user;

View File

@ -31,6 +31,10 @@ class Module extends BaseModule
* @var bool whether to display flash messages or not * @var bool whether to display flash messages or not
*/ */
public $enableFlashMessages = true; public $enableFlashMessages = true;
/**
* @var bool whether to be able to, as an admin, impersonate other users
*/
public $enableSwitchIdentities = true;
/** /**
* @var bool whether to generate passwords automatically and remove the password field from the registration form * @var bool whether to generate passwords automatically and remove the password field from the registration form
*/ */
@ -92,7 +96,6 @@ class Module extends BaseModule
* @see Bootstrap::buildClassMap() for more details * @see Bootstrap::buildClassMap() for more details
*/ */
public $classMap = []; public $classMap = [];
/** /**
* @var array the url rules (routes) * @var array the url rules (routes)
*/ */
@ -102,12 +105,14 @@ class Module extends BaseModule
'<action:(register|resend)>' => 'registration/<action>', '<action:(register|resend)>' => 'registration/<action>',
'confirm/<id:\d+>/<code:[A-Za-z0-9_-]+>' => 'registration/confirm', 'confirm/<id:\d+>/<code:[A-Za-z0-9_-]+>' => 'registration/confirm',
'forgot' => 'recovery/request', 'forgot' => 'recovery/request',
'recover/<id:\d+>/<code:[A-Za-z0-9_-]+>' => 'recovery/reset', 'recover/<id:\d+>/<code:[A-Za-z0-9_-]+>' => 'recovery/reset'
'settings/<action:\w+>' => 'settings/<action>',
]; ];
/** /**
* @var string * @var string
*/ */
public $viewPath = '@Da/User/resources/views'; public $viewPath = '@Da/User/resources/views';
/**
* @var string the session key name to impersonate users
*/
public $switchIdentitySessionKey = 'yuik_user';
} }

View File

@ -0,0 +1,69 @@
<?php
/*
* This file is part of the 2amigos/yii2-usuario project.
*
* (c) 2amigOS! <http://2amigos.us/>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Da\User\Service;
use Da\User\Contracts\ServiceInterface;
use Da\User\Controller\AdminController;
use Da\User\Event\UserEvent;
use Da\User\Model\User;
use Da\User\Module;
use Da\User\Query\UserQuery;
use Da\User\Traits\ContainerAwareTrait;
use Yii;
use yii\web\ForbiddenHttpException;
use yii\web\IdentityInterface;
class SwitchIdentityService implements ServiceInterface
{
use ContainerAwareTrait;
protected $controller;
protected $switchIdentitySessionKey;
protected $userId;
protected $userQuery;
public function __construct(AdminController $controller, $userId, UserQuery $userQuery)
{
/** @var Module $module */
$module = $controller->module;
$this->controller = $controller;
$this->switchIdentitySessionKey = $module->switchIdentitySessionKey;
$this->userId = $userId;
$this->userQuery = $userQuery;
}
public function run()
{
$session = Yii::$app->session;
if (null === $this->userId) { // switch back identities
$user = $this->userQuery->whereId($session->get($this->switchIdentitySessionKey))->one();
$session->remove($this->switchIdentitySessionKey);
} else {
/** @var User $identity */
$identity = Yii::$app->user->identity;
if (!$identity->getIsAdmin()) {
// Only admins allowed on module. Developers can override the service and implement different
// approach. For example, by roles other than, and including, admin.
throw new ForbiddenHttpException();
}
$user = $this->userQuery->whereId($this->userId)->one();
$session->set($this->switchIdentitySessionKey, $this->userId);
}
$event = $this->make(UserEvent::class, [$user]);
$this->controller->trigger(UserEvent::EVENT_BEFORE_SWITCH_IDENTITY, $event);
/** @var IdentityInterface $user */
Yii::$app->user->switchIdentity($user, $session->timeout);
$this->controller->trigger(UserEvent::EVENT_AFTER_SWITCH_IDENTITY, $event);
}
}

View File

@ -18,10 +18,13 @@ use yii\widgets\Pjax;
* @var $this yii\web\View * @var $this yii\web\View
* @var $dataProvider yii\data\ActiveDataProvider * @var $dataProvider yii\data\ActiveDataProvider
* @var $searchModel Da\User\Search\UserSearch * @var $searchModel Da\User\Search\UserSearch
* @var $module Da\User\Module
*/ */
$this->title = Yii::t('usuario', 'Manage users'); $this->title = Yii::t('usuario', 'Manage users');
$this->params['breadcrumbs'][] = $this->title; $this->params['breadcrumbs'][] = $this->title;
$module = Yii::$app->getModule('user');
?> ?>
<?php $this->beginContent('@Da/User/resources/views/shared/admin_layout.php') ?> <?php $this->beginContent('@Da/User/resources/views/shared/admin_layout.php') ?>
@ -106,7 +109,27 @@ $this->params['breadcrumbs'][] = $this->title;
], ],
[ [
'class' => 'yii\grid\ActionColumn', 'class' => 'yii\grid\ActionColumn',
'template' => '{update} {delete}', 'template' => '{switch} {update} {delete}',
'buttons' => [
'switch' => function ($url, $model) use ($module) {
if ($model->id != Yii::$app->user->id && $module->enableSwitchIdentities) {
return Html::a(
'<span class="glyphicon glyphicon-user"></span>',
['/user/admin/switch-identity', 'id' => $model->id],
[
'title' => Yii::t('usuario', 'Impersonate this user'),
'data-confirm' => Yii::t(
'usuario',
'Are you sure you want to switch to this user for the rest of this Session?'
),
'data-method' => 'POST',
]
);
}
return null;
}
]
], ],
], ],
] ]