Laravel не имеет обёртки над низкоувровневыми методами имперсонализации. Этот пакет был разработан под сильным впечатлением от имперсонализации Symfony, которая является намного более гибкой, чем несколько просмотренных реализаций для Laravel. Пакет полностью реализует поведение управления имперсонализацией GET-параметрами. Также данный пакет не ограничивает Вас в использовании произвольных user provider'ов (например, можно работать с пользователями через Propel), guard'ов и позволяет использовать в качестве шаблонизатора Twig. Некоторые идеи были заимствованы из других пакетов имперсонализации для Laravel (:+1: спасибо их авторам!).
composer require scif/laravel-pretend
Добавьте сервис провайдер в config/app.php
после сервисных провайдеров Laravel, но до своих собственных:
'providers' => [
…
Scif\LaravelPretend\LaravelPretendServiceProvider::class,
/*
* Application Service Providers...
*/
…
]
Добавьте middleware, реализующий имперсонализацию одним из способов:
- в свой класс
Kernel
:Это наиболее популярный способ и покрывает большинство случаев, которые я могу представить.protected $middlewareGroups = [ 'web' => [ … Scif\LaravelPretend\Middleware\Impersonate::class, ],
- или любым другим доступным способом, в случае особенных требований.
Заключительным шагом в установке является конфигурирование авторизации через gate.
В пакете поставляется gate называющий impersonate
. Данный gate проверяет реализует ли модель вашего пользователя интерфейс Scif\LaravelPretend\Interfaces\Impersonable
и вызывает метод canImpersonate(): bool
.
В этом случае ваша модель может выглядеть так:
class User extends Authenticatable implements Impersonable
{
…
public function canImpersonate(): bool
{
return $this->isAdmin();
}
}
☝️ По своему усмотрению Вы можете использовать штатную реализацию gate'а либо переопределить её в своём AuthServiceProvider'е, также можно переопределить имя gate'а в конфигурации.
Скопировать конфигурационный файл к себе в проект можно стандартной командой vendor:publish
:
php ./artisan vendor:publish --provider=Scif\\LaravelPretend\\LaravelPretendServiceProvider --tag=config
Конфигурационный файл содержит всего две директивы:
return [
'impersonate' => [
'user_identifier' => 'email',
'auth_check' => 'impersonate',
]
];
user_identifier
— эта строка, будет использоваться как имя поля по которому запрашивается объект пользователя из user provider'а (методretrieveByCredentials()
). Значение по-умолчаниюemail
позволяет создавать url для имперсонализации более красивыми:[email protected]
намного понятней, чем?_switch_user=43
при использованииid
. Но это полностью на Ваше усмотрение.auth_check
— эта строка, является именем Gate, используемого для проверки наличия прав у пользователя для применения имперсонализации. Вы можете легко переопределить имя gate'а и создать его вAuthServiceProvider
своего приложения.
Как было указано выше, этот пакет повторяет стиль Symfony по работе с GET-параметрами для управления имперсонализацией.
Использовать в blade
весьма просто:
// создаём ссылку для имперсонализации
{{ route('home', ['_switch_user' => '[email protected]']) }}
// выход из режима имперсонализации
@if ($app['impersonator']->isImpersonated())
<a href="{{ route('home', ['_switch_user' => '_exit']) }}">Exit impersonation</a>
@else
<a href="{{ route('logout') }}">Logout</a>
@endif
А вот так можно использовать в twig
:
// создаём ссылку для имперсонализации
{{ route('home', {'_switch_user': '[email protected]'}) }}
// более продвинутое использование
{% if auth_user() %}
{% if app.impersonator.impersonated %}
<a class="btn btn-default" href="{{ route('home', {'_switch_user': '_exit'}) }}">Exit impersonation</a>
{% else %}
<form action="{{ route('logout') }}" method="post">
{{ csrf_field() }}
<button class="btn btn-default">Logout</button>
</form>
{% endif %}
{% endif %}
Во время входа и выхода из режима имперсонализации этот пакет создаёт события: Scif\LaravelPretend\Event\Impersontated
, Scif\LaravelPretend\Event\Unimpersontated
.
Именами событий являются их полные имена классов (с namespace'ом), поэтому простейший обработчик событий будет выглядеть так:
use Scif\LaravelPretend\Event\Impersontated;
…
Event::listen(Impersonated::class, function (Impersonated $event) {
//
});
Вы можете использовать штатный middleware ForbidImpersonation
чтобы запретить использование имперсонализации, например для некоторых груп маршрутов, маршрутов или контроллеров.
Да, т.к. PHP7 потрясающ! Если есть большое желание использовать со старым PHP5 — создайте тикет и я подумаю о создании отдельной ветки или иного подходящего решения.
Любая помощь всегда приветствуется. Не стесняйтесь — помогите проекту стать ещё лучше!