Файл настроек
core/App/config/pbauth.php — единственный пульт управления компонентом. Через него меняются шаблоны, правила проверки, редиректы, группы пользователей, пределы, соцсети, второй фактор и даже сами контроллеры.
Файл принадлежит сайту: компонент его только читает и никогда не поставляет, поэтому обновление не может его затереть. Создавать его не нужно — установщик кладёт заготовку, в которой перечислены все настройки закомментированными.
Поставочные значения лежат рядом, в core/components/pbauth/config/defaults.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 убирает поставочное совсем.
Шаблоны и формы
'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 в шаблон вовсе»: шаблон сайта рисует форму сам.
Подробнее с примерами — в быстром старте.
Куда уводить после успеха
'redirects' => [
'login' => '/profile',
'logout' => '/',
'reset_password' => '/profile',
'verify_email' => '/profile',
'impersonate' => '/',
],Вернуть туда, откуда пришёл
Если человека завернуло на вход с закрытой страницы, его можно вернуть обратно. Имя GET-параметра — настройка; пустая строка выключает возможность:
'login_redirect_param' => 'redirect',В форму входа добавьте скрытое поле, а ссылку на вход стройте с параметром (/login?redirect=/profile/ads):
<input type="hidden" name="redirect" value="{$.get.redirect|escape}">Принимаются только пути внутри сайта
Значение приводится к пути: со схемой (https://…), с хостом или протокол-относительное //host отбрасывается, и человек уходит на обычный адрес. Без этого форма входа стала бы открытым редиректом — готовым инструментом для фишинга со ссылкой на ваш домен.
Группы и аватары
'user_groups' => ['Users'],
'avatar_path' => 'assets/images/avatars/:user_id',user_groups — список, поэтому сайт заменяет его целиком. Поставка пустая: новый пользователь не попадает ни в одну группу, пока вы этого не скажете.
Пределы на отправку писем
'register_ip_limit' => 3, // регистраций с одного IP в час
'resend_verification_limit' => 3, // повторных ссылок на один адрес в час
'forgot_password_limit' => 3, // писем восстановления на один адрес в час0 — без ограничения. Пределы нужны не от спама в чистом виде: формы восстановления и повторной отправки принимают любой адрес и отвечают одинаково, поэтому без предела через них можно рассылать письма чужим людям с вашего домена.
Один вход на учётную запись
'single_session' => false,По умолчанию под одним логином можно сидеть с любого числа устройств — так устроен MODX. Для платного аккаунта это значит, что одну подписку раздают по кругу на десятерых.
С true новый вход закрывает предыдущий: тот, кто вошёл раньше, на следующем же своём действии оказывается разлогинен и видит на форме входа «под этим логином вошли с другого устройства».
Как это сделано. При входе за учётной записью закрепляется идентификатор сессии, а на каждом запросе он сверяется с текущим. Не совпал — значит эту сессию уже сменила другая, и она закрывается. Чужие сессии никто не ищет и не убивает: хранилище сессий бывает разное — файлы, база, redis, — а так работает везде одинаково.
Чего это не касается: менеджера MODX (вход в панель не закрывает сайт и наоборот) и кнопки «Авторизоваться на сайте» — менеджер, посмотревший сайт глазами пользователя, не выставляет самого пользователя за дверь.
При включении никого не выкидывает. У тех, кто уже вошёл, закреплённой сессии ещё нет, и первый же их запрос просто закрепляет текущую. Выселение начинается со следующего входа.
Нужно событие плагина
Настройка требует, чтобы к плагину pbAuth было прикреплено OnHandleRequest с приоритетом раньше PageBlocks (в пакете это -10). Пакет делает это сам; вручную — только там, где компонент раскладывали файлами, минуя пакет.
Второй фактор и соцсети
Обе подсистемы настраиваются здесь же, но у них своя страница с устройством и подводными камнями: «Соцсети, 2FA, вход под пользователем».
'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' => [],
],Подмена контроллера
'controllers' => [
'register' => \PageBlocks\App\Http\Controllers\Auth\RegisterController::class,
],Последний рычаг, когда настроек и событий не хватило. Разобрано на примере в «События и свой код».
Слушатели событий
'listeners' => [
Dispatcher::AFTER_REGISTER => [SendWelcomeLetter::class],
],Четырнадцать событий, список и содержимое $params — в «События и свой код».
Файл целиком
Писать нужно только то, что отличается от поставочного.
<?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.