About Me
Мy name is Dzianis Kotau. I'm Solutions Architect and Zend Certified PHP Engineer. I'm PHP evangelist and loved in it.
MoonShine Impersonate
MoonShine Impersonate предоставляет возможность подмены пользователя в проектах на Laravel с использованием админ-панели MoonShine. Функциональность подмены пользователя позволяет админстратору войти на сайт как реальный пользователь. Это может быть полезно, чтобы посмотреть, как сайт виден обычному пользователю, воспроизвести баги от его имени и т.д.
Содержимое
Установка
MoonShine Impersonate
спроектирован для использования в составе админ-панели MoonShine. Поэтому, сперва установите
админ-панель, следуя инструкциям с официального сайте MoonShine. Затем установите данный пакет при помощи
команды:
composer require jampire/moonshine-impersonate
Настройка
MoonShine Impersonate
способен работать из коробки с настройками по умолчанию. Но вы можете опубликовать его
настройки в свою директорию config
и изменть нужные пареметры (зачастую в файле .env
):
php artisan vendor:publish --provider="Jampire\MoonshineImpersonate\ImpersonateServiceProvider" --tag=config
Также можно опубликовать файлы локализации для более тонкой настройки:
php artisan vendor:publish --provider="Jampire\MoonshineImpersonate\ImpersonateServiceProvider" --tag=lang
Использование
Базовое использование
Включение подмены пользователя
Т.к. данный пакет работает с системой авторизации, то применять его можно на модели User
. Для этого создайте
MoonShine ресурс, использующий модель авторизации User
вашего приложения.
Для примера, создадим следующий MoonShine ресурс:
<?php
declare(strict_types=1);
namespace App\MoonShine\Resources;
use Illuminate\Database\Eloquent\Model;
use App\Models\User;
use MoonShine\Fields\Email;
use MoonShine\Fields\Text;
use MoonShine\Resources\ModelResource;
use MoonShine\Decorations\Block;
use MoonShine\Fields\ID;
class UserResource extends ModelResource
{
protected string $model = User::class;
protected string $title = 'Users';
public function fields(): array
{
return [
Block::make([
ID::make()->sortable(),
Text::make('Name', 'name'),
Email::make('E-mail', 'email'),
]),
];
}
public function rules(Model $item): array
{
return [];
}
}
Для добавления действия подмены пользователя пакет MoonShine Impersonate
предоставляет свою кнопку действия
EnterImpersonationActionButton
. Для его добавления воспользуйтесь методом buttons()
ресурса UserResource
:
<?php
declare(strict_types=1);
namespace App\MoonShine\Resources;
use Jampire\MoonshineImpersonate\UI\ActionButtons\EnterImpersonationActionButton
use MoonShine\Resources\ModelResource;
class UserResource extends ModelResource
{
// ...
public function buttons(): array
{
return [
EnterImpersonationActionButton::resolve()->showInDropdown(),
];
}
}
За тонкую настройку этого действия отвечают секция buttons.enter
файла конфигурации и секция ui.buttons.enter
файлов локализации.
После подключения данного действия ваш ресурс Users
может выглядеть следующим образом:
При нажатии на эту кнопку вы переключитесь на выбранного пользователя:
Отключение подмены пользователя
Пакет MoonShine Impersonate
предоставляет несколько способов отключения режима подмены пользователя. Рассмотрим
способ размещения кнопки отключения в заголовке шаблона. Разместив кнопку в заголовке, вы всегда будите знать, что
находитесь в режиме подмены пользователя, т.к. кнопка будет видна на всех страницах админ-панели (когда режим подмены
остановлен, кнопка видна не будет).
Для того, чтобы размещать кастомные элементы в заголовке шаблона, вам нужно опубликовать шаблон и отредактировать его (что обычно и происходит, когда вы настраиваете админ-панель):
php artisan moonshine:publish
Для отключения действия подмены пользователя пакет MoonShine Impersonate
предоставляет свой компонент
StopImpersonation
. Для размещения компонента в заголовке добавьте его в компонет Header
опубликонвааного шаблона:
<?php
declare(strict_types=1);
namespace App\MoonShine;
// ...
use MoonShine\Components\Layout\{Header,
LayoutBlock,
LayoutBuilder};
use Jampire\MoonshineImpersonate\UI\Components\StopImpersonation;
use MoonShine\Contracts\MoonShineLayoutContract;
final class MoonShineLayout implements MoonShineLayoutContract
{
public static function build(): LayoutBuilder
{
return LayoutBuilder::make([
// ...
LayoutBlock::make([
// ...
Header::make([
// ...
StopImpersonation::make(),
]),
// ...
])->customAttributes(['class' => 'layout-page']),
]);
}
}
Middleware
Для своей работы режим подмены пользователя использует ImpersonateMiddleware
класс. По-умолчанию он работает с
маршрутами (routes
) в группе web
. Если вы хотите добавить этот middleware
к другим маршрутам, воспольуйтесь
псевдонимом impersonate
. Например, его можно подключить в контроллере:
class PostController extends Controller
{
public function __construct()
{
$this->middleware('impersonate');
}
}
Разрешения
По умолчанию, любой администратор может подменять любого пользователя. Если вы желаете более тонкую настройку
разрешений (permissions), можно воспользоваться интерфейсами Impersonable
и BeImpersonable
и реализовать методы
canImpersonate()
и canBeImpersonated()
соответственно.
Например, чтобы контролировать, кто из админстраторов может подменять пользователя, нужно реализовать метод
canImpersonate()
на моделе администратора MoonshineUser
:
<?php
declare(strict_types=1);
namespace App\Models;
use Jampire\MoonshineImpersonate\Services\Contracts\Impersonable;
use MoonShine\Models\MoonshineUser as BaseUser;
use MoonShine\Models\MoonshineUserRole;
class MoonshineUser extends BaseUser implements Impersonable
{
// ...
public function canImpersonate(): bool
{
return $this->moonshine_user_role_id === MoonshineUserRole::DEFAULT_ROLE_ID;
}
}
А чтобы контролировать, кого из пользователей можно подменять, нужно реализовать метод canBeImpersonated()
на моделе авторизации User
:
<?php
declare(strict_types=1);
namespace App\Models;
use Illuminate\Foundation\Auth\User as BaseUser;
use Illuminate\Support\Str;
use Jampire\MoonshineImpersonate\Services\Contracts\BeImpersonable;
class User extends BaseUser implements BeImpersonable
{
// ...
public function canBeImpersonated(): bool
{
return !Str::endsWith($this->email, '@verysecureemail.com');
}
}
Запись событий (логирование)
Если вы желаете, то можете включить запись событий переключения пользователя в журнал MoonShine (по-умолчанию
отключено). Для включение режима записи вам необходимо установить пакет MoonShine Changelog и добавить
трейт HasChangeLog
к модели авторизации User
:
<?php
declare(strict_types=1);
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use MoonShine\ChangeLog\Traits\HasChangeLog;
class User extends Authenticatable
{
use HasChangeLog;
// ...
}
При старте режима подмены пользователя в журнале (таблица moonshine_change_logs
) появится следующая запись:
id: 7
moonshine_user_id: 1 # пользователь, который запустил режим подмены (админ)
changelogable_type: App\Models\User # модель авторизации пользователя
changelogable_id: 4 # пользователь, которого подменяют
states_before: "impersonation_stopped" # статус приложения до начала подмены
states_after: "impersonation_entered" # статус приложения после начала подмены
created_at: 2023-05-25 23:25:11
updated_at: 2023-05-25 23:25:11
При окончании режима подмены пользователя в журнале (таблица moonshine_change_logs
) появится следующая запись:
id: 8
moonshine_user_id: 1 # пользователь, который остановил режим подмены (админ)
changelogable_type: App\Models\User # модель авторизации пользователя
changelogable_id: 4 # пользователь, которого подменяли
states_before: "impersonation_entered" # статус приложения до остановки подмены
states_after: "impersonation_stopped" # статус приложения после остановки подмены
created_at: 2023-05-25 23:25:37
updated_at: 2023-05-25 23:25:37
События
После старта и отмены режима подмены пользователя отправляются события ImpersonationEntered
и ImpersonationStopped
соответственно. Оба эти события обладают следующими открытыми свойствами:
Authenticatable $impersonator
- пользователь, запустивший/остановивший режим подмены (админ);Authenticatable $impersonated
- пользователь, которого подменяют.
Расширенное использование
Расширенное использование подразумевает, что вы хорошо владете админ-панелью MoonShine
и фреймворком Laravel
.
Помимо рассмотренных выше кнопки EnterImpersonationActionButton
и компонента StopImpersonation
, данный пакет также
предоставляет кнопку действия StopImpersonationActionButton
, которая действует аналогично компоненту
StopImpersonation
, но предназначена для страниц и ресурсов. Кнопки и компонент обладают всеми свойствами,
присущими кнопкам и компонентам в MoonShine
. Например, кнопки можно отрисовать в in-line
или dropdown
режимах.
Также вы можете самостоятельно реализовать свои кнопки и компоненты, используя админ-панель MoonShine
и ресурсы
пакета MoonShine Impersonate
. Пример реализации кнопки включения режима подмены пользователя:
use Illuminate\Contracts\Auth\Authenticatable;
use Jampire\MoonshineImpersonate\Actions\EnterAction;
use MoonShine\ActionButtons\ActionButton;
ActionButton::make(
label: __('impersonate::ui.buttons.enter.label'),
url: static fn (mixed $data): string => route('impersonate.enter', [
config('impersonate.resource_item_key') => $data->getKey(),
]),
)
->canSee(
callback: fn (Authenticatable $item): bool => app(EnterAction::class)->manager->canEnter($item),
)
->icon(config('impersonate.buttons.enter.icon'));
Cписок ресурсов пакета MoonShine Impersonate
Jampire\MoonshineImpersonate\UI\ActionButtons\EnterImpersonationActionButton
- кнопка включения режима подмены пользователяJampire\MoonshineImpersonate\UI\ActionButtons\StopImpersonationActionButton
- кнопка отключения режима подмены пользователяJampire\MoonshineImpersonate\UI\Components\StopImpersonation
- компонент отключения режима подмены пользователяJampire\MoonshineImpersonate\Services\ImpersonateManager
- управления режимами подменыroute('impersonate.enter')
-GET
маршрут включения режима подмены пользователяroute('impersonate.enter-confirm')
-POST
маршрут включения режима подмены пользователя (используется в модальном окне confirm)route('impersonate.stop')
-GET
маршрут отключения режима подмены пользователяJampire\MoonshineImpersonate\Actions\EnterAction
- включение режима подмены пользователяJampire\MoonshineImpersonate\Actions\StopAction
- отключение режима подмены пользователяJampire\MoonshineImpersonate\Events\ImpersonationEntered
- событие включения режима подмены пользователяJampire\MoonshineImpersonate\Events\ImpersonationStopped
- событие отключения режима подмены пользователя
Ссылки
Дополнительные ресурсы
Функционал подмены пользователя реализуют некоторые админ-панели. Например: