Dzianis Kotau
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

Документация версии 2.x

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 может выглядеть следующим образом:

Start Impersonation Button

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

Impersonation Mode

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

Stop Impersonation Button

За отрисовку данной кнопки отвечает опция 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 соответственно. Оба эти события обладают следующими открытыми свойствами:

Дополнительные ресурсы

Функционал подмены пользователя реализуют некоторые админ-панели. Например: