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 v1
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
Также можно опубликовать все ресурсы пакета для ещё более тонкой настройки (или же по отдельным тегам lang, views,
view-components):
php artisan vendor:publish --provider="Jampire\MoonshineImpersonate\ImpersonateServiceProvider"
Использование
Базовое использование
Т.к. данный пакет работает с системой авторизации, то применять его можно на модели 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\Resource;
use MoonShine\Fields\ID;
use MoonShine\Actions\FiltersAction;
class UserResource extends Resource
{
public static string $model = User::class;
public static string $title = 'Users';
public static string $orderType = 'ASC';
public function fields(): array
{
return [
ID::make()->sortable(),
Text::make('Name', 'name'),
Email::make('E-mail', 'email'),
];
}
public function rules(Model $item): array
{
return [];
}
public function search(): array
{
return ['id'];
}
public function filters(): array
{
return [];
}
public function actions(): array
{
return [
FiltersAction::make(trans('moonshine::ui.filters')),
];
}
public function itemActions(): array
{
return [];
}
}
Для добавления действия подмены пользователя пакет MoonShine Impersonate предоставляет своё действие карточки
EnterImpersonationItemAction. Для его добавления воспользуйтесь методом itemActions() ресурса UserResource:
<?php
declare(strict_types=1);
namespace App\MoonShine\Resources;
use Jampire\MoonshineImpersonate\UI\ItemActions\EnterImpersonationItemAction;
use MoonShine\Resources\Resource;
class UserResource extends Resource
{
// ...
public function itemActions(): array
{
return [
EnterImpersonationItemAction::make()->resolve(),
];
}
}
За тонкую настройку этого действия отвечают секция buttons.enter файла конфигурации и секция ui.buttons.enter
файлов локализации.
После подключения данного действия ваш ресурс Users может выглядеть следующим образом:

При нажатии на эту кнопку вы переключитесь на выбранного пользователя:

В заголовке админ-панели появится кнопка
Остановить подмену пользователя, которая будет видна на любой странице админ-панели. Таким образом, вы всегда
будите помнить, что находитесь в режиме подмены пользователя:

За отрисовку данной кнопки отвечает опция buttons.stop.enabled файла конфигурации. Эта опция перезапишет содержимое
опции header файла конфигурации moonshine. Если это не то, что вам нужно, вы можете отключить отрисовку кнопки
в файле .env при помощи переменной окружения MS_IMPERSONATE_STOP_BUTTON_ENABLED:
MS_IMPERSONATE_STOP_BUTTON_ENABLED=false
а саму кнопку установить в нужном вам месте при помощи компонента x-impersonate-stop.
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 (по-умолчанию
отключено). Включение режима записи осуществляется путём добавления трейта HasMoonShineChangeLog к модели авторизации
User (согласно документации MoonShine):
<?php
declare(strict_types=1);
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use MoonShine\Traits\Models\HasMoonShineChangeLog;
class User extends Authenticatable
{
use HasMoonShineChangeLog;
// ...
}
При старте режима подмены пользователя в журнале (таблица 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- пользователь, которого подменяют.
Ссылки
Дополнительные ресурсы
Функционал подмены пользователя реализуют некоторые админ-панели. Например: