Skip to content

Файл настроек ​

core/App/config/pbauth.php — единственный пульт управления компонентом. Через него меняются шаблоны, правила проверки, редиректы, группы пользователей, пределы, соцсети, второй фактор и даже сами контроллеры.

Файл принадлежит сайту: компонент его только читает и никогда не поставляет, поэтому обновление не может его затереть. Создавать его не нужно — установщик кладёт заготовку, в которой перечислены все настройки закомментированными.

Поставочные значения лежат рядом, в core/components/pbauth/config/defaults.php. Смотреть можно, править нет: файл компонента перезаписывается при обновлении.

Как склеиваются значения ​

Словари дополняются по ключам вглубь, списки сайт заменяет целиком.

php
// поставка                        // сайт                    // результат
'rules' => [                       'rules' => [               'rules' => [
    'register' => [                    'register' => [            'register' => [
        'username' => '…',                 'phone' => '…',            'username' => '…',
        'email'    => '…',             ],                             'email'    => '…',
    ],                             ],                                 'phone'    => '…',
],                                                                ],
                                                              ],
'user_groups' => [],               'user_groups' => ['Users'] 'user_groups' => ['Users']

Иначе rules.profile приходилось бы переписывать целиком ради одного поля, а список групп нельзя было бы сократить — только дополнить.

Словарём решает только поставочная сторона

Пустая секция у сайта ('rules' => [] — а именно так выглядит незаполненная заготовка) сама считалась бы списком и стирала бы все поставочные правила. Поэтому «словарь это или список» определяется по поставочному значению, а не по вашему.

Правила проверки склеиваются по полю: неизвестное поле добавляется, известное заменяется, null убирает поставочное совсем.

Шаблоны и формы ​

php
'views' => [
    'auth'    => 'file:auth/templates/auth',
    'profile' => 'file:auth/templates/profile',
],

'forms' => [
    'login'               => 'form.login',
    'register'            => 'form.register',
    'forgot_password'     => 'form.forgotPassword',
    'reset_password'      => 'form.resetPassword',
    'change_password'     => 'form.changePassword',
    'confirm_password'    => 'form.confirmPassword',
    'resend_verification' => 'form.resendVerification',
    'two_factor_challenge'=> 'form.twoFactorChallenge',
    'two_factor'          => 'form.twoFactor',
    'social_email'        => 'form.socialEmail',
    'profile'             => 'form.profile',
],

Разрешение шаблона: ключ с именем действия перебивает ключ с именем обёртки — views.two_factor сильнее views.profile. forms.<действие> = null означает «не передавать $form в шаблон вовсе»: шаблон сайта рисует форму сам.

Подробнее с примерами — в быстром старте.

Куда уводить после успеха ​

php
'redirects' => [
    'login'          => '/profile',
    'logout'         => '/',
    'reset_password' => '/profile',
    'verify_email'   => '/profile',
    'impersonate'    => '/',
],

Вернуть туда, откуда пришёл ​

Если человека завернуло на вход с закрытой страницы, его можно вернуть обратно. Имя GET-параметра — настройка; пустая строка выключает возможность:

php
'login_redirect_param' => 'redirect',

В форму входа добавьте скрытое поле, а ссылку на вход стройте с параметром (/login?redirect=/profile/ads):

html
<input type="hidden" name="redirect" value="{$.get.redirect|escape}">

Принимаются только пути внутри сайта

Значение приводится к пути: со схемой (https://…), с хостом или протокол-относительное //host отбрасывается, и человек уходит на обычный адрес. Без этого форма входа стала бы открытым редиректом — готовым инструментом для фишинга со ссылкой на ваш домен.

Группы и аватары ​

php
'user_groups' => ['Users'],
'avatar_path' => 'assets/images/avatars/:user_id',

user_groups — список, поэтому сайт заменяет его целиком. Поставка пустая: новый пользователь не попадает ни в одну группу, пока вы этого не скажете.

Пределы на отправку писем ​

php
'register_ip_limit'         => 3,   // регистраций с одного IP в час
'resend_verification_limit' => 3,   // повторных ссылок на один адрес в час
'forgot_password_limit'     => 3,   // писем восстановления на один адрес в час

0 — без ограничения. Пределы нужны не от спама в чистом виде: формы восстановления и повторной отправки принимают любой адрес и отвечают одинаково, поэтому без предела через них можно рассылать письма чужим людям с вашего домена.

Один вход на учётную запись ​

php
'single_session' => false,

По умолчанию под одним логином можно сидеть с любого числа устройств — так устроен MODX. Для платного аккаунта это значит, что одну подписку раздают по кругу на десятерых.

С true новый вход закрывает предыдущий: тот, кто вошёл раньше, на следующем же своём действии оказывается разлогинен и видит на форме входа «под этим логином вошли с другого устройства».

Как это сделано. При входе за учётной записью закрепляется идентификатор сессии, а на каждом запросе он сверяется с текущим. Не совпал — значит эту сессию уже сменила другая, и она закрывается. Чужие сессии никто не ищет и не убивает: хранилище сессий бывает разное — файлы, база, redis, — а так работает везде одинаково.

Чего это не касается: менеджера MODX (вход в панель не закрывает сайт и наоборот) и кнопки «Авторизоваться на сайте» — менеджер, посмотревший сайт глазами пользователя, не выставляет самого пользователя за дверь.

При включении никого не выкидывает. У тех, кто уже вошёл, закреплённой сессии ещё нет, и первый же их запрос просто закрепляет текущую. Выселение начинается со следующего входа.

Нужно событие плагина

Настройка требует, чтобы к плагину pbAuth было прикреплено OnHandleRequest с приоритетом раньше PageBlocks (в пакете это -10). Пакет делает это сам; вручную — только там, где компонент раскладывали файлами, минуя пакет.

Второй фактор и соцсети ​

Обе подсистемы настраиваются здесь же, но у них своя страница с устройством и подводными камнями: «Соцсети, 2FA, вход под пользователем».

php
'two_factor_enabled'       => true,
'two_factor_window'        => 1,
'two_factor_challenge_ttl' => 300,
'two_factor_attempts'      => 5,
'two_factor_backup_codes'  => 8,
'two_factor_issuer'        => '',

'social' => [
    'enabled'       => true,
    'require_email' => true,
    'providers'     => [/* … */],
    'drivers'       => [],
],

Подмена контроллера ​

php
'controllers' => [
    'register' => \PageBlocks\App\Http\Controllers\Auth\RegisterController::class,
],

Последний рычаг, когда настроек и событий не хватило. Разобрано на примере в «События и свой код».

Слушатели событий ​

php
'listeners' => [
    Dispatcher::AFTER_REGISTER => [SendWelcomeLetter::class],
],

Четырнадцать событий, список и содержимое $params — в «События и свой код».

Файл целиком ​

Писать нужно только то, что отличается от поставочного.

php
<?php

use Boshnik\PbAuth\Events\Dispatcher;

return [
    // Шаблоны-обёртки страниц
    'views' => [
        'auth'    => 'file:auth/templates/auth',
        'profile' => 'file:auth/templates/profile',
    ],

    // Чанк формы для страницы. null — не передавать $form в шаблон
    'forms' => [
        'login'    => 'form.login',
        'register' => 'form.register',
        'profile'  => 'form.profile',
    ],

    // Поля форм и правила проверки. null убирает поставочное поле
    'rules' => [
        'register' => ['phone' => 'required|string'],
        'profile'  => ['fullname' => null],
    ],

    // Куда уводить после успеха
    'redirects' => [
        'login'          => '/',
        'logout'         => '/',
        'reset_password' => '/',
        'verify_email'   => '/',
        'impersonate'    => '/',
    ],

    // «Авторизоваться на сайте» из менеджера
    'impersonate_enabled' => true,

    // Один вход на учётную запись: новый вход закрывает предыдущий
    'single_session' => false,

    // Имя GET-параметра для возврата после входа. '' — выключить
    'login_redirect_param' => 'redirect',

    // Группы, в которые попадает новый пользователь. Список — заменяется целиком
    'user_groups' => ['Users'],

    // Куда складывать аватары, :user_id подставится
    'avatar_path' => 'assets/images/avatars/:user_id',

    // Пределы на письма. 0 — без ограничения
    'register_ip_limit'         => 3,
    'resend_verification_limit' => 3,
    'forgot_password_limit'     => 3,

    // Подтверждение входа кодом
    'two_factor_enabled'       => true,
    'two_factor_window'        => 1,
    'two_factor_challenge_ttl' => 300,
    'two_factor_attempts'      => 5,
    'two_factor_backup_codes'  => 8,
    'two_factor_issuer'        => '',

    // Вход через сторонние службы
    'social' => [
        'enabled'       => true,
        'require_email' => true,
        'providers'     => [
            'google' => ['client_id' => '', 'client_secret' => ''],
        ],
        'drivers' => [],
    ],

    // Свои контроллеры вместо поставочных
    'controllers' => [],

    // Свои классы на события
    'listeners' => [
        Dispatcher::AFTER_REGISTER => [],
    ],
];

Образец с комментариями везёт сам компонент: core/components/pbauth/docs/pbauth.config.example.php.

pbAuth — вход, регистрация и профиль для PageBlocks