Случайно споткнулся о не совсем понятную вещь.
Писал некий механизм, проверяющий, что среди ролей пользователя имеются 'manager'
или 'administrator'
. Пользователь, к слову, не именно текущий, а скажем так, инициировавший некоторое событие в системе (по сути что-то вроде журнала/истории изменения данных сотрудниками сайта). Ну, примерно так:
<?php
...
$user = \Drupal\user\Entity\User::load($orig_uid);
if ($user->hasRole('manager') || $user->hasRole('administrator')) {
$uid = $orig_uid;
}
...
?>
Захожу под uid = 1
(т.е. самый толстый админ). Тестирую этот механизм и обнаруживаю, что именно для меня он не работает. Иду смотреть что не так в профиль uid 1. И вижу, что у супер-пупер-админа стоит только лишь одна галка напротив роли "Аутентифицированный пользователь".
Включаю роль "администратор", сохраняю. "Изменения сохранены". Ок, открываю профиль, кручу вниз и вижу, что чекбокс роли "Администратор" по-прежнему отключен.
Лёгкий разрыв шаблона, как говорится. Опять включаю эту галку и, за компанию, дополнительно включаю роль "менеджер", сохраняю. "Изменения сохранены". Опять открываю профиль, кручу вниз - в поле все эти установленные чекбоксы по-прежнему отключены (кроме, разумеется, "Аутентифицированный пользователь").
Возникает смутное предположение: я, возможно, отстал от жизни и теперь всё как-то должно происходить иначе? На всякий случай выбираю другого пользователя и ставлю ему чекбоксы админа и менеджера. С замиранием сердца сохраняю профиль и - внезапно - галки установились!
Но это же не мой профиль, а что делать с моим?
Тут я наконец обнаруживаю, что в списке пользователей третья колонка отображает список ролей конкретного пользователя. И - внезапно! - у uid = 1
теперь стоит две роли: "Менеджер" и "Администратор".
Не веря своим глазам, возвращаюсь в профиль и вижу ту же унылую картину: чекбоксы этих ролей выключены.
Ну и ладно, ну их к лешему, эти чекбоксы. Возвращаюсь к своему коду и проверяю работу. Да, всё ОК, роль "Администратор" присутствуют, код отрабатывает так, как намечалось.
Возникают два вопроса:
1. Это какое-то штатное поведение формы профиля для uid = 1
? Форму профиля не альтерили, нет никакой сторонней "химии".
2. Какое решение для вышеприведённого кода тогда более уместно в случае, если нет возможности поставить необходимые роли для uid = 1
? Проверять тогда не $user->hasRole('administrator')
, а $user->id() == 1
? Например (применительно к вышеприведённому коду):
<?php
...
$user = \Drupal\user\Entity\User::load($orig_uid);
if ($user->hasRole('manager') || $user->hasRole('administrator') || $user->id() == 1) {
$uid = $orig_uid;
}
...
?>
Комментарии
PS. Продолжение истории.
Через час после написания топика обнаружил, что проверка роли а-ля
$user->hasRole('administrator')
по-прежнему не работает. Я был введён в заблуждение другим условием (оно шло выше и в код примера не попало).В общем, установка роли 'administrator' для
UID = 1
не сказывается на программной проверке. МетодhasRole()
похоже вообще не обнаруживает никакие роли дляUID = 1
(для любого другого пользователя с ролью менеджера всё работает). Я не пойму, в чём тут дело. Пока решил вопрос так, как писал выше (т.е. добавил$user->id() == 1
) :<?php
...
$user = \Drupal\user\Entity\User::load($orig_uid);
if ($user->hasRole('manager') || $user->hasRole('administrator') || $user->id() == 1) {
$uid = $orig_uid;
}
...
?>
Но как-то мне это не нравится.
Да. Юзер с id = 1 всегда имеет все права на всё и это не изменить. Странно, что ты этого не знал
Не использовать юзера с id = 1 в работе.
Спасибо за подтверждение. Мне и самому странно. Но:
1. В своё оправдание могу заметить, что в каких-то предыдущих версиях D (и, по-моему, ещё даже в 8.x) чекбоксы у
uid = 1
по всем ролям всё же стояли. Понятно, что у него и так все права по умолчанию.2. Опять же сбивает с толку то, что установка чекбоксов перед сохранениям профиля всё же сказывается на отображении ролей в списке пользователей (картинка №2 выше). То есть они вроде бы обрабатываются при сохранении, но при повторной загрузке формы ставятся в
FALSE
(причём за исключением'authenticated'
).3. Сам факт того, что все чекбоксы кроме
'authenticated'
доступны для включения (т.е. не'disabled'
) опять же создаёт какую-то неоднозначность относительно их использования.4. Наконец, я помню, что метод
hasRole()
(или, возможно,User::getRoles()
- точно уже не помню) на D8 таки возвращал роль/роли дляuid = 1
. То есть, для меня это сейчас реально какой-то сюрприз.Ну вот это, к сожалению, исключено.
Это абсолютно ни на что не влияет.
Для новичков да. Странно, что у тебя такие же чувства.
Кто заставляет тебя использовать этого юзера и почему?
Да понимаю, что не влияет. ) Но тем не менее hasRole(), как я писал выше, у меня таки работал ранее. Собственно, задача была добиться именно обнаружения соответствующих ролей у UID = 1.
Ну да, значит, я новичок, раз уж испытываю какие-то странные чувства. Вы как бы второй раз уже намекаете на это. Что ж мне теперь делать-то?
Формально - никто. Но есть ряд соображений, по которым создание отдельного профиля/аккаунта для "главного" админа вызовет лишние вопросы и в будущем - может запутать ситуацию с аккаунтами в целом. Это не мой проект, я тут исполнитель.
Я не намекаю. Я недоумеваю
Смысл главного админа в том, что он всё может и у него всё отображается. Если ты хочешь ограничивать в чем-то главного админа, то лучше создать для этого отдельную роль и отдельного юзера
Очень похоже на какой-то глюк. В коде методов hasRole и getRoles нет никаких особых кейсов для uid=1. И вообще, права первого юзера неограничены при проверке пермишенов. А вот проверка ролей должна работать, как у всех. Я постоянно с этим сталкиваюсь, если во вьюхе поставить ограничение доступа по роли, которой нет у админа, то админу пишет "доступ запрещён". Если же ограничить доступ не по роли, а по пермишену, то всё показывает.
На стандартном профиле, "из коробки" всё норм. Описанное поведение выше отсутствует.
Ну что, бывает и так. Давно не занимался вопросами ролей, в частности - особенностями получения ролей для
uid = 1
.Разумеется, я прогуглил вопрос прежде, чем открывать топик. И в том-то и дело, что никаких явных подтверждений вышеописанного поведения не нашёл. Как и в целом - описания состояния чекбоксов ролей для
uid = 1
. То есть, эмпирически/субъективно мы тут все знаем, что "толстый админ" в Друпале имеет по умолчанию все права, причём установленные перманентным образом посколькуuid = 1
. Но это никак не помогает пониманию странной ситуации с чекбоксами и тем более странной - с методами::hasRole()
и::getRoles()
.Кроме того, это создаёт ещё одну проблему: как донести эти эмпирически полученные сведения об особенностях Друпала до заказчика? До человека, который привык понимать, что если чекбокс установлен - значит "оно включено". И если тут какое-то другое поведение, которое нужно трактовать со ссылкой типа "ну вот Друпал - он такой, у него так", то, боюсь, что это опять же зацепит вопросы кармы и репутации Друпала. Как-то так.
Ну и, как писал выше, есть ряд соображений (которые долго излагать), по которым лучше обрабатывать
uid = 1
так же, как и остальных администраторов, то есть - по роли.В общем, спасибо за ответы.
Спасибо. Я что-то теряюсь и не знаю, что тут может быть причиной. Есть какие-либо соображения?
Из контрибных модулей на проекте установлено немного, и (вроде бы) ни один из них не должен влиять на сущности пользователя, роли и разрешения:
Остальное - кастомные модули, но все писал я и ни в одном нет никаких хуков/надстроек, каким-либо образом изменяющих стандартную форму и механизм сохранения профилей пользователей.
имхо, на стандартный профиль не просто так намекнул... Думаю, где-то там твой баг.
Скорее всего, тут где-то ответ или в связанных issues:
https://www.drupal.org/project/drupal/issues/540008
Да тоже стандартный профиль. К сожалению, уже не могу сказать, наблюдалась ли эта проблема сразу после установки. Обнаружил только прошлой ночью.
Да, я ночью уже просматривал это. Не обнаружил ничего, явно объясняющего вышеописанное. Возможно, стоит внимательнее перечитать.
Продолжение истории.
К сожалению, решение вышеописанной проблемы с чекбоксами и категорическим отказом обнаруживать роли у
uid = 1
так и не нашёл.Но добавилась ещё одна странность. Потребовалось ввести в поля стандартного профиля пользователя одно кастомное поле с JSON-данными типа простого неформатированного long-text и записывать в него некоторое множество специфических настроек, уникальных для текущего пользователя. Ну, просто обычный длинный текст, иными словами.
И в дополнение к вышеописанному поведению с чекбоксами профиль
uid = 1
тут тоже наотрез отказался сохранять что-либо в кастомное поле. Неважно как именно сохраняются данные: программно ли или через UI-поля профиля (как обычная произвольная/тестовая строка) - результат отрицательный. Сущность сохраняется, но поле не инициализировано и даже вообще отсутствует в entity values (как отрапортовалdpm
). Примечательно, что для любого другого пользователя с любой ролью сохранение полей профиля работает как обычно.Поотключал некоторые модули, потенциально (на мой взгляд) способные вмешиваться в сохранение сущности пользователя (например, devel и пр.). Безрезультатно. Разбираться в проблеме уже, к сожалению, не было времени. Было в итоге согласовано и принято решение не использовать аккаунт
uid = 1
в дальнейшей повседневной деятельности. Как предлагал выше ivnish. Хоть это и может создать некоторые неудобства в будущем.В общем, капитуляция.
По прежнему, приветствуются любые соображения по этому поводу.
Может, банально, баг в админской теме? Кастомные js-скрипты/библиотеки?
Да вроде бы не похоже.
Тема админки стандартная, seven для D9. Кастомные скрипты для админки - да, подключаются, но только на специфических роутах/формах, для профиля пользователя ничего такого нет. Да и для другого любого пользователя всё работает. Например, могу зайти под другим админом (не uid = 1) и что угодно вбить/сохранить в полях своего профиля. Включая пресловутые чекбоксы - они тоже работают.